xref: /petsc/src/snes/interface/snes.c (revision 3201ab8d70a3eea669f338f8bd746342de1cf5db)
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 
120c3339decSBarry Smith   Logically Collective
1214936397dSBarry Smith 
1222fe279fdSBarry Smith   Input Parameter:
123f6dfbefdSBarry Smith . snes - the `SNES` context
1244936397dSBarry Smith 
12528529972SSatish Balay   Level: advanced
1264936397dSBarry Smith 
127ced0f3aeSBarry Smith   Notes:
128ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
129ced0f3aeSBarry Smith 
130ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
131ced0f3aeSBarry Smith 
132f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
133f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
134f0b84518SBarry Smith 
1358434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
136ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
1374936397dSBarry Smith @*/
138d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes)
139d71ae5a4SJacob Faibussowitsch {
1404936397dSBarry Smith   PetscFunctionBegin;
1410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1425f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain");
1434936397dSBarry Smith   snes->domainerror = PETSC_TRUE;
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1454936397dSBarry Smith }
1464936397dSBarry Smith 
1476a388c36SPeter Brune /*@
148f6dfbefdSBarry Smith   SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation.
14907b62357SFande Kong 
150c3339decSBarry Smith   Logically Collective
15107b62357SFande Kong 
1522fe279fdSBarry Smith   Input Parameter:
153f6dfbefdSBarry Smith . snes - the `SNES` context
15407b62357SFande Kong 
15507b62357SFande Kong   Level: advanced
15607b62357SFande Kong 
157ced0f3aeSBarry Smith   Notes:
158ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
159ced0f3aeSBarry Smith 
160ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
161ced0f3aeSBarry Smith 
162f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
163f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
164f0b84518SBarry Smith 
1658434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`,
166ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
16707b62357SFande Kong @*/
168d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes)
169d71ae5a4SJacob Faibussowitsch {
17007b62357SFande Kong   PetscFunctionBegin;
17107b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1725f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense");
17307b62357SFande Kong   snes->jacobiandomainerror = PETSC_TRUE;
1743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17507b62357SFande Kong }
17607b62357SFande Kong 
17707b62357SFande Kong /*@
178f6dfbefdSBarry Smith   SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after
179420bcc1bSBarry 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.
180b351a90bSFande Kong 
181c3339decSBarry Smith   Logically Collective
182b351a90bSFande Kong 
183b351a90bSFande Kong   Input Parameters:
18420f4b53cSBarry Smith + snes - the `SNES` context
185f6dfbefdSBarry Smith - flg  - indicates if or not to check Jacobian domain error after each Jacobian evaluation
186b351a90bSFande Kong 
187b351a90bSFande Kong   Level: advanced
188b351a90bSFande Kong 
189f6dfbefdSBarry Smith   Note:
190f6dfbefdSBarry Smith   Checks require one extra parallel synchronization for each Jacobian evaluation
191f6dfbefdSBarry Smith 
1928434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()`
193b351a90bSFande Kong @*/
194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
195d71ae5a4SJacob Faibussowitsch {
196b351a90bSFande Kong   PetscFunctionBegin;
197b351a90bSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
198b351a90bSFande Kong   snes->checkjacdomainerror = flg;
1993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
200b351a90bSFande Kong }
201b351a90bSFande Kong 
202b351a90bSFande Kong /*@
203420bcc1bSBarry Smith   SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation.
2048383d7d7SFande Kong 
205c3339decSBarry Smith   Logically Collective
2068383d7d7SFande Kong 
2072fe279fdSBarry Smith   Input Parameter:
208f6dfbefdSBarry Smith . snes - the `SNES` context
2098383d7d7SFande Kong 
2102fe279fdSBarry Smith   Output Parameter:
211420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation
2128383d7d7SFande Kong 
2138383d7d7SFande Kong   Level: advanced
2148383d7d7SFande Kong 
2158434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()`
2168383d7d7SFande Kong @*/
217d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
218d71ae5a4SJacob Faibussowitsch {
2198383d7d7SFande Kong   PetscFunctionBegin;
2208383d7d7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2214f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
2228383d7d7SFande Kong   *flg = snes->checkjacdomainerror;
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2248383d7d7SFande Kong }
2258383d7d7SFande Kong 
2268383d7d7SFande Kong /*@
227420bcc1bSBarry Smith   SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()`
2286a388c36SPeter Brune 
229f6dfbefdSBarry Smith   Logically Collective
2306a388c36SPeter Brune 
2312fe279fdSBarry Smith   Input Parameter:
232f6dfbefdSBarry Smith . snes - the `SNES` context
2336a388c36SPeter Brune 
2342fe279fdSBarry Smith   Output Parameter:
235f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise.
2366a388c36SPeter Brune 
237f6dfbefdSBarry Smith   Level: developer
2386a388c36SPeter Brune 
2391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`
2406a388c36SPeter Brune @*/
241d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
242d71ae5a4SJacob Faibussowitsch {
2436a388c36SPeter Brune   PetscFunctionBegin;
2446a388c36SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2454f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
2466a388c36SPeter Brune   *domainerror = snes->domainerror;
2473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2486a388c36SPeter Brune }
2496a388c36SPeter Brune 
25007b62357SFande Kong /*@
251420bcc1bSBarry Smith   SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()`
25207b62357SFande Kong 
253c3339decSBarry Smith   Logically Collective
25407b62357SFande Kong 
2552fe279fdSBarry Smith   Input Parameter:
256f6dfbefdSBarry Smith . snes - the `SNES` context
25707b62357SFande Kong 
2582fe279fdSBarry Smith   Output Parameter:
259f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise.
26007b62357SFande Kong 
26107b62357SFande Kong   Level: advanced
26207b62357SFande Kong 
2631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()`
26407b62357SFande Kong @*/
265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror)
266d71ae5a4SJacob Faibussowitsch {
26707b62357SFande Kong   PetscFunctionBegin;
26807b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2694f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
27007b62357SFande Kong   *domainerror = snes->jacobiandomainerror;
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27207b62357SFande Kong }
27307b62357SFande Kong 
274ffeef943SBarry Smith /*@
275f6dfbefdSBarry Smith   SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
27655849f57SBarry Smith 
277c3339decSBarry Smith   Collective
27855849f57SBarry Smith 
27955849f57SBarry Smith   Input Parameters:
280e4094ef1SJacob Faibussowitsch + snes   - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
281f6dfbefdSBarry Smith            some related function before a call to `SNESLoad()`.
282f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
28355849f57SBarry Smith 
28455849f57SBarry Smith   Level: intermediate
28555849f57SBarry Smith 
286f6dfbefdSBarry Smith   Note:
287420bcc1bSBarry Smith   The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored.
28855849f57SBarry Smith 
2891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
29055849f57SBarry Smith @*/
291d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
292d71ae5a4SJacob Faibussowitsch {
29355849f57SBarry Smith   PetscBool isbinary;
294060da220SMatthew G. Knepley   PetscInt  classid;
29555849f57SBarry Smith   char      type[256];
29655849f57SBarry Smith   KSP       ksp;
2972d53ad75SBarry Smith   DM        dm;
2982d53ad75SBarry Smith   DMSNES    dmsnes;
29955849f57SBarry Smith 
30055849f57SBarry Smith   PetscFunctionBegin;
3012d53ad75SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
30255849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3045f80ce2aSJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
30555849f57SBarry Smith 
3069566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
3075f80ce2aSJacob Faibussowitsch   PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3089566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3099566063dSJacob Faibussowitsch   PetscCall(SNESSetType(snes, type));
310dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, load, viewer);
3119566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3129566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &dmsnes));
3139566063dSJacob Faibussowitsch   PetscCall(DMSNESLoad(dmsnes, viewer));
3149566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
3159566063dSJacob Faibussowitsch   PetscCall(KSPLoad(ksp, viewer));
3163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31755849f57SBarry Smith }
3186a388c36SPeter Brune 
3199804daf3SBarry Smith #include <petscdraw.h>
320e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
321e04113cfSBarry Smith   #include <petscviewersaws.h>
322bfb97211SBarry Smith #endif
3238404b7f3SBarry Smith 
324ffeef943SBarry Smith /*@
325dc4c0fb0SBarry Smith   SNESViewFromOptions - View a `SNES` based on values in the options database
326fe2efc57SMark 
327c3339decSBarry Smith   Collective
328fe2efc57SMark 
329fe2efc57SMark   Input Parameters:
330f6dfbefdSBarry Smith + A    - the `SNES` context
331dc4c0fb0SBarry Smith . obj  - Optional object that provides the options prefix for the checks
332736c3998SJose E. Roman - name - command line option
333fe2efc57SMark 
334fe2efc57SMark   Level: intermediate
335f6dfbefdSBarry Smith 
3361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
337fe2efc57SMark @*/
338d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
339d71ae5a4SJacob Faibussowitsch {
340fe2efc57SMark   PetscFunctionBegin;
341fe2efc57SMark   PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
344fe2efc57SMark }
345fe2efc57SMark 
346789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
347789d8953SBarry Smith 
348ffeef943SBarry Smith /*@
349dc4c0fb0SBarry Smith   SNESView - Prints or visualizes the `SNES` data structure.
3509b94acceSBarry Smith 
351c3339decSBarry Smith   Collective
352fee21e36SBarry Smith 
353c7afd0dbSLois Curfman McInnes   Input Parameters:
354f6dfbefdSBarry Smith + snes   - the `SNES` context
355f6dfbefdSBarry Smith - viewer - the `PetscViewer`
356c7afd0dbSLois Curfman McInnes 
3579b94acceSBarry Smith   Options Database Key:
358f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3599b94acceSBarry Smith 
360dc4c0fb0SBarry Smith   Level: beginner
361dc4c0fb0SBarry Smith 
3629b94acceSBarry Smith   Notes:
3639b94acceSBarry Smith   The available visualization contexts include
364f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
365f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
366c8a8ba5cSLois Curfman McInnes   output where only the first processor opens
367c8a8ba5cSLois Curfman McInnes   the file.  All other processors send their
368c8a8ba5cSLois Curfman McInnes   data to the first processor to print.
3699b94acceSBarry Smith 
370052bf0daSPierre Jolivet   The available formats include
371f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
372f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
373052bf0daSPierre Jolivet 
3743e081fefSLois Curfman McInnes   The user can open an alternative visualization context with
375f6dfbefdSBarry Smith   `PetscViewerASCIIOpen()` - output to a specified file.
3769b94acceSBarry Smith 
377f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
378595c91d4SBarry Smith 
3791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3809b94acceSBarry Smith @*/
381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
382d71ae5a4SJacob Faibussowitsch {
383fa9f3622SBarry Smith   SNESKSPEW     *kctx;
38494b7f48cSBarry Smith   KSP            ksp;
3857f1410a3SPeter Brune   SNESLineSearch linesearch;
38672a02f06SBarry Smith   PetscBool      iascii, isstring, isbinary, isdraw;
3872d53ad75SBarry Smith   DMSNES         dmsnes;
388e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
389536b137fSBarry Smith   PetscBool issaws;
390bfb97211SBarry Smith #endif
3919b94acceSBarry Smith 
3923a40ed3dSBarry Smith   PetscFunctionBegin;
3930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39448a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
3950700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
396c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, viewer, 2);
39774679c65SBarry Smith 
3989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
4009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
402e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
4039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
404bfb97211SBarry Smith #endif
40532077d6dSBarry Smith   if (iascii) {
406dc0571f2SMatthew G. Knepley     SNESNormSchedule normschedule;
4078404b7f3SBarry Smith     DM               dm;
4088434afd1SBarry Smith     SNESJacobianFn  *cJ;
4098404b7f3SBarry Smith     void            *ctx;
410789d8953SBarry Smith     const char      *pre = "";
411dc0571f2SMatthew G. Knepley 
4129566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
41348a46eb9SPierre Jolivet     if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  SNES has not been set up so information may be incomplete\n"));
414e7788613SBarry Smith     if (snes->ops->view) {
4159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
416dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, view, viewer);
4179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
4180ef38995SBarry Smith     }
41977e5a1f9SBarry Smith     if (snes->max_funcs == PETSC_UNLIMITED) {
42077e5a1f9SBarry Smith       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its));
42177e5a1f9SBarry Smith     } else {
42263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
42377e5a1f9SBarry Smith     }
4249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42548a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4279566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4289566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
42948a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4309b94acceSBarry Smith     if (snes->ksp_ewconv) {
431fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4329b94acceSBarry Smith       if (kctx) {
43363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4349566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4359566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4369b94acceSBarry Smith       }
4379b94acceSBarry Smith     }
438eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
440eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
44163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
442eb1f6c34SBarry Smith     }
443eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
445eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
44663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
447eb1f6c34SBarry Smith     }
4489566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4499566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
450789d8953SBarry Smith     if (snes->mf_operator) {
4519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
452789d8953SBarry Smith       pre = "Preconditioning ";
453789d8953SBarry Smith     }
4548404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4568404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
458789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
459789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
460789d8953SBarry Smith       MatFDColoring fdcoloring;
4619566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
462789d8953SBarry Smith       if (fdcoloring) {
4639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
464789d8953SBarry Smith       } else {
4659566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
466789d8953SBarry Smith       }
467996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4689566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4698404b7f3SBarry Smith     }
4700f5bd95cSBarry Smith   } else if (isstring) {
471317d6ea6SBarry Smith     const char *type;
4729566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4739566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
474dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47555849f57SBarry Smith   } else if (isbinary) {
47655849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
47755849f57SBarry Smith     MPI_Comm    comm;
47855849f57SBarry Smith     PetscMPIInt rank;
47955849f57SBarry Smith     char        type[256];
48055849f57SBarry Smith 
4819566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
483dd400576SPatrick Sanan     if (rank == 0) {
4849566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4859566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4869566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48755849f57SBarry Smith     }
488dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
48972a02f06SBarry Smith   } else if (isdraw) {
49072a02f06SBarry Smith     PetscDraw draw;
49172a02f06SBarry Smith     char      str[36];
49289fd9fafSBarry Smith     PetscReal x, y, bottom, h;
49372a02f06SBarry Smith 
4949566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4959566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4969566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4979566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
4989566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
49989fd9fafSBarry Smith     bottom = y - h;
5009566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
501dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
502e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
503536b137fSBarry Smith   } else if (issaws) {
504d45a07a7SBarry Smith     PetscMPIInt rank;
5052657e9d9SBarry Smith     const char *name;
506d45a07a7SBarry Smith 
5079566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
509dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
510d45a07a7SBarry Smith       char dir[1024];
511d45a07a7SBarry Smith 
5129566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5139566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
514792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51548a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5169566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
517792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
518f05ece33SBarry Smith     }
519bfb97211SBarry Smith #endif
52072a02f06SBarry Smith   }
52172a02f06SBarry Smith   if (snes->linesearch) {
5229566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5249566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
52619bcc07fSBarry Smith   }
527efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5299566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5314a0c5b0cSMatthew G Knepley   }
5329566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5339566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5349566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5359566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5362c155ee1SBarry Smith   if (snes->usesksp) {
5379566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5399566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5412c155ee1SBarry Smith   }
54272a02f06SBarry Smith   if (isdraw) {
54372a02f06SBarry Smith     PetscDraw draw;
5449566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5459566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5467f1410a3SPeter Brune   }
5473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5489b94acceSBarry Smith }
5499b94acceSBarry Smith 
55076b2cf59SMatthew Knepley /*
55176b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
55276b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
55376b2cf59SMatthew Knepley */
55476b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
555a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5566849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55776b2cf59SMatthew Knepley 
558ac226902SBarry Smith /*@C
559f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
56076b2cf59SMatthew Knepley 
56176b2cf59SMatthew Knepley   Not Collective
56276b2cf59SMatthew Knepley 
56376b2cf59SMatthew Knepley   Input Parameter:
56476b2cf59SMatthew Knepley . snescheck - function that checks for options
56576b2cf59SMatthew Knepley 
566420bcc1bSBarry Smith   Calling sequence of `snescheck`:
567420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
568420bcc1bSBarry Smith 
56976b2cf59SMatthew Knepley   Level: developer
57076b2cf59SMatthew Knepley 
5711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
57276b2cf59SMatthew Knepley @*/
573420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
574d71ae5a4SJacob Faibussowitsch {
57576b2cf59SMatthew Knepley   PetscFunctionBegin;
57663a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57776b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57976b2cf59SMatthew Knepley }
58076b2cf59SMatthew Knepley 
581d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
582d71ae5a4SJacob Faibussowitsch {
583aa3661deSLisandro Dalcin   Mat          J;
584895c21f2SBarry Smith   MatNullSpace nullsp;
585aa3661deSLisandro Dalcin 
586aa3661deSLisandro Dalcin   PetscFunctionBegin;
5870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
588aa3661deSLisandro Dalcin 
58998613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
59098613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5919566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
59298613b67SLisandro Dalcin   }
59398613b67SLisandro Dalcin 
5940fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
595aa3661deSLisandro Dalcin   if (version == 1) {
5969566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5979566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5989566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5991e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
6000fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
6015f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
602570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
603f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
604aa3661deSLisandro Dalcin #else
6052479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
606aa3661deSLisandro Dalcin #endif
6070fdf79fbSJacob Faibussowitsch   }
608aa3661deSLisandro Dalcin 
60901c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
610895c21f2SBarry Smith   if (snes->jacobian) {
6119566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6121baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
613895c21f2SBarry Smith   }
614895c21f2SBarry Smith 
61563a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
616d3462f78SMatthew Knepley   if (hasOperator) {
617aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
618aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6199566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
620aa3661deSLisandro Dalcin   } else {
621aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
62201c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
623b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6249566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
625172a4300SPeter Brune     } else {
626789d8953SBarry Smith       KSP       ksp;
627789d8953SBarry Smith       PC        pc;
628789d8953SBarry Smith       PetscBool match;
629789d8953SBarry Smith 
6309566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
631aa3661deSLisandro Dalcin       /* Force no preconditioner */
6329566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6339566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6342698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
635aa3661deSLisandro Dalcin       if (!match) {
6369566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6379566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
638aa3661deSLisandro Dalcin       }
639aa3661deSLisandro Dalcin     }
640789d8953SBarry Smith   }
6419566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
643aa3661deSLisandro Dalcin }
644aa3661deSLisandro Dalcin 
645d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
646d71ae5a4SJacob Faibussowitsch {
647dfe15315SJed Brown   SNES snes = (SNES)ctx;
6480298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
649dfe15315SJed Brown 
650dfe15315SJed Brown   PetscFunctionBegin;
65116ebb321SJed Brown   if (PetscLogPrintInfo) {
65216ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6539566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6549566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6559566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6569566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65763a3b9bcSJacob 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));
65816ebb321SJed Brown   }
659dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
660dfe15315SJed Brown   else {
6619566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
662dfe15315SJed Brown     Xfine = Xfine_named;
663dfe15315SJed Brown   }
6649566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
665907f5c5aSLawrence Mitchell   if (Inject) {
6669566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
667907f5c5aSLawrence Mitchell   } else {
6689566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6699566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
670907f5c5aSLawrence Mitchell   }
6719566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6729566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
674dfe15315SJed Brown }
675dfe15315SJed Brown 
676d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
677d71ae5a4SJacob Faibussowitsch {
67816ebb321SJed Brown   PetscFunctionBegin;
6799566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68116ebb321SJed Brown }
68216ebb321SJed Brown 
683a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
684a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
685d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
686d71ae5a4SJacob Faibussowitsch {
687caa4e7f2SJed Brown   SNES            snes = (SNES)ctx;
68897d931d1SStefano Zampini   DMSNES          sdm;
6890298fd71SBarry Smith   Vec             X, Xnamed = NULL;
690dfe15315SJed Brown   DM              dmsave;
6914e269d77SPeter Brune   void           *ctxsave;
6928434afd1SBarry Smith   SNESJacobianFn *jac = NULL;
693caa4e7f2SJed Brown 
694caa4e7f2SJed Brown   PetscFunctionBegin;
695dfe15315SJed Brown   dmsave = snes->dm;
6969566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
697dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
69897d931d1SStefano Zampini   else {
699309d62e6SStefano Zampini     PetscBool has;
700309d62e6SStefano Zampini 
70197d931d1SStefano Zampini     /* We are on a coarser level, this vec was initialized using a DM restrict hook */
702309d62e6SStefano Zampini     PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has));
703309d62e6SStefano Zampini     PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol");
70497d931d1SStefano Zampini     PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
705dfe15315SJed Brown     X = Xnamed;
7069566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
7074e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
70848a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7094e269d77SPeter Brune   }
7104e269d77SPeter Brune 
7112b93b426SMatthew G. Knepley   /* Compute the operators */
71297d931d1SStefano Zampini   PetscCall(DMGetDMSNES(snes->dm, &sdm));
71397d931d1SStefano Zampini   if (Xnamed && sdm->ops->computefunction) {
71497d931d1SStefano Zampini     /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
71597d931d1SStefano Zampini        We make sure of this here. Disable affine shift since it is for the finest level */
71697d931d1SStefano Zampini     Vec F, saverhs = snes->vec_rhs;
71797d931d1SStefano Zampini 
71897d931d1SStefano Zampini     snes->vec_rhs = NULL;
71997d931d1SStefano Zampini     PetscCall(DMGetGlobalVector(snes->dm, &F));
72097d931d1SStefano Zampini     PetscCall(SNESComputeFunction(snes, X, F));
72197d931d1SStefano Zampini     PetscCall(DMRestoreGlobalVector(snes->dm, &F));
72297d931d1SStefano Zampini     snes->vec_rhs = saverhs;
72397d931d1SStefano Zampini     snes->nfuncs--; /* Do not log coarser level evaluations */
72497d931d1SStefano Zampini   }
72597d931d1SStefano Zampini   /* Make sure KSP DM has the Jacobian computation routine */
72697d931d1SStefano Zampini   if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7279566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
72897d931d1SStefano Zampini 
7292b93b426SMatthew G. Knepley   /* Put the previous context back */
73048a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7314e269d77SPeter Brune 
7329566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
733dfe15315SJed Brown   snes->dm = dmsave;
7343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
735caa4e7f2SJed Brown }
736caa4e7f2SJed Brown 
7376cab3a1bSJed Brown /*@
738dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7396cab3a1bSJed Brown 
7406cab3a1bSJed Brown   Collective
7416cab3a1bSJed Brown 
7424165533cSJose E. Roman   Input Parameter:
74320f4b53cSBarry Smith . snes - `SNES` object to configure
7446cab3a1bSJed Brown 
7456cab3a1bSJed Brown   Level: developer
7466cab3a1bSJed Brown 
747dc4c0fb0SBarry Smith   Note:
748dc4c0fb0SBarry 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`
749dc4c0fb0SBarry Smith 
75073a84a35SBarry Smith   Developer Note:
75173a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
75273a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
75373a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
75473a84a35SBarry Smith 
7551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7566cab3a1bSJed Brown @*/
757d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
758d71ae5a4SJacob Faibussowitsch {
7596cab3a1bSJed Brown   DM     dm;
760942e3340SBarry Smith   DMSNES sdm;
7616cab3a1bSJed Brown 
7626cab3a1bSJed Brown   PetscFunctionBegin;
7639566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7649566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
76573a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7666cab3a1bSJed Brown     Mat   J;
7676cab3a1bSJed Brown     void *functx;
7689566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7699566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7709566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7719566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7729566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7739566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
774caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7756cab3a1bSJed Brown     Mat J, B;
7769566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7779566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7789566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7799566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
78006f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7819566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7829566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7839566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
784caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7851ba9b98eSMatthew G. Knepley     PetscDS   prob;
7866cab3a1bSJed Brown     Mat       J, B;
7871ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7881ba9b98eSMatthew G. Knepley 
7896cab3a1bSJed Brown     J = snes->jacobian;
7909566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7919566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7929566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7939566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7949566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7959566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7986cab3a1bSJed Brown   }
799caa4e7f2SJed Brown   {
800caa4e7f2SJed Brown     KSP ksp;
8019566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
8029566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
8039566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
804caa4e7f2SJed Brown   }
8053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8066cab3a1bSJed Brown }
8076cab3a1bSJed Brown 
808d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
809d71ae5a4SJacob Faibussowitsch {
8105e7c47f3SMatthew G. Knepley   PetscInt i;
8115e7c47f3SMatthew G. Knepley 
8125e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8133ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
8145e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
8155e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
8165e7c47f3SMatthew G. Knepley     PetscDraw             draw;
8175e7c47f3SMatthew G. Knepley     PetscReal             lpause;
8185e7c47f3SMatthew G. Knepley 
8195e7c47f3SMatthew G. Knepley     if (!vf) continue;
8205e7c47f3SMatthew G. Knepley     if (vf->lg) {
8215e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
8225e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
8239566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
8249566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8259566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8269566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8279566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8285e7c47f3SMatthew G. Knepley     } else {
8295e7c47f3SMatthew G. Knepley       PetscBool isdraw;
8305e7c47f3SMatthew G. Knepley 
8315e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
8325e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
8339566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
8345e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
8359566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
8369566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8379566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8389566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8399566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8405e7c47f3SMatthew G. Knepley     }
8415e7c47f3SMatthew G. Knepley   }
8423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8435e7c47f3SMatthew G. Knepley }
8445e7c47f3SMatthew G. Knepley 
845fde5950dSBarry Smith /*@C
846fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
847fde5950dSBarry Smith 
848c3339decSBarry Smith   Collective
849fde5950dSBarry Smith 
850fde5950dSBarry Smith   Input Parameters:
851dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
852fde5950dSBarry Smith . name         - the monitor type one is seeking
853fde5950dSBarry Smith . help         - message indicating what monitoring is done
854fde5950dSBarry Smith . manual       - manual page for the monitor
855fde5950dSBarry Smith . monitor      - the monitor function
856f6dfbefdSBarry 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
857fde5950dSBarry Smith 
858420bcc1bSBarry Smith   Calling sequence of `monitor`:
859420bcc1bSBarry Smith + snes - the nonlinear solver context
860420bcc1bSBarry Smith . it   - the current iteration
861420bcc1bSBarry Smith . r    - the current function norm
862420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
863420bcc1bSBarry Smith 
864420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
865420bcc1bSBarry Smith + snes - the nonlinear solver context
866420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
867420bcc1bSBarry Smith 
868f6dfbefdSBarry Smith   Options Database Key:
869f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
870f6dfbefdSBarry Smith 
871f6dfbefdSBarry Smith   Level: advanced
872fde5950dSBarry Smith 
873648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
874db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
875e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
876db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
877c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
878db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
879db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
880fde5950dSBarry Smith @*/
881420bcc1bSBarry 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))
882d71ae5a4SJacob Faibussowitsch {
883fde5950dSBarry Smith   PetscViewer       viewer;
884fde5950dSBarry Smith   PetscViewerFormat format;
885fde5950dSBarry Smith   PetscBool         flg;
886fde5950dSBarry Smith 
887fde5950dSBarry Smith   PetscFunctionBegin;
888648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
889fde5950dSBarry Smith   if (flg) {
890d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8919566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
892648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
8931baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8949566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
895fde5950dSBarry Smith   }
8963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
897fde5950dSBarry Smith }
898fde5950dSBarry Smith 
899a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
900d71ae5a4SJacob Faibussowitsch {
901a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
902a4598233SStefano Zampini 
9030f0abf79SStefano Zampini   PetscFunctionBegin;
9040f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
905a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
906a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
907a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
908a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
909a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
910a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
9110f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
912a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
9130f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
9140f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
9150f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
9160f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
9170f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
9180f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
9190f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
9200f0abf79SStefano Zampini   PetscOptionsEnd();
9213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9220f0abf79SStefano Zampini }
9230f0abf79SStefano Zampini 
9249b94acceSBarry Smith /*@
925f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9269b94acceSBarry Smith 
927c3339decSBarry Smith   Collective
928c7afd0dbSLois Curfman McInnes 
9299b94acceSBarry Smith   Input Parameter:
930f6dfbefdSBarry Smith . snes - the `SNES` context
9319b94acceSBarry Smith 
93236851e7fSLois Curfman McInnes   Options Database Keys:
933f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
934b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
93577e5a1f9SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
93677e5a1f9SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
937e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
938b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
939b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
94077e5a1f9SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
9414839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
942ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
943a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9443d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
945e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9463d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
947ceaaa498SBarry 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.
948fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
949fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
950fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
951fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9524619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
953459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9545e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
955e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
956e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
957ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
958b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
959ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
960e62ac41dSBarry 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.
961e62ac41dSBarry 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.
96282738288SBarry Smith 
963f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
964fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9654b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
96636851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
96736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
96836851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
96936851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
97036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
97136851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
97282738288SBarry Smith 
973dc4c0fb0SBarry Smith   Level: beginner
974dc4c0fb0SBarry Smith 
97511ca99fdSLois Curfman McInnes   Notes:
976ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
977ec5066bdSBarry Smith 
978420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
979420bcc1bSBarry Smith   and computing explicitly with
980f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
98183e2fdc7SBarry Smith 
982420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9839b94acceSBarry Smith @*/
984d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
985d71ae5a4SJacob Faibussowitsch {
9868afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
98777e5a1f9SBarry Smith   PetscInt    i, indx, lag, grids, max_its, max_funcs;
98804d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
989649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
99085385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9910f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
992c40d0f55SPeter Brune   PCSide      pcside;
993a64e098fSPeter Brune   const char *optionsprefix;
99477e5a1f9SBarry Smith   PetscReal   rtol, abstol, stol;
9959b94acceSBarry Smith 
9963a40ed3dSBarry Smith   PetscFunctionBegin;
9970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9989566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
999d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
1000639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
10019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
1002d64ed03dSBarry Smith   if (flg) {
10039566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
10047adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
10059566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
1006d64ed03dSBarry Smith   }
1007186905e3SBarry Smith 
100877e5a1f9SBarry Smith   abstol    = snes->abstol;
100977e5a1f9SBarry Smith   rtol      = snes->rtol;
101077e5a1f9SBarry Smith   stol      = snes->stol;
101177e5a1f9SBarry Smith   max_its   = snes->max_its;
101277e5a1f9SBarry Smith   max_funcs = snes->max_funcs;
101377e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL));
101477e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL));
101577e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL));
101677e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL));
101777e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL));
101877e5a1f9SBarry Smith   PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs));
101977e5a1f9SBarry Smith 
102077e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg));
102177e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol));
102277e5a1f9SBarry Smith 
102377e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg));
102477e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures));
102577e5a1f9SBarry Smith 
102677e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg));
102777e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures));
102877e5a1f9SBarry Smith 
10299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
103285385478SLisandro Dalcin 
10339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1034a8054027SBarry Smith   if (flg) {
10355f80ce2aSJacob 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");
10369566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1037a8054027SBarry Smith   }
10389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10391baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1041e35cf81dSBarry Smith   if (flg) {
10425f80ce2aSJacob 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");
10439566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1044e35cf81dSBarry Smith   }
10459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10461baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
104737ec4e1aSPeter Brune 
10489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10491baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1050a8054027SBarry Smith 
1051400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
105285385478SLisandro Dalcin   if (flg) {
105385385478SLisandro Dalcin     switch (indx) {
1054d71ae5a4SJacob Faibussowitsch     case 0:
1055d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1056d71ae5a4SJacob Faibussowitsch       break;
1057d71ae5a4SJacob Faibussowitsch     case 1:
1058d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1059d71ae5a4SJacob Faibussowitsch       break;
1060d71ae5a4SJacob Faibussowitsch     case 2:
1061d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1062d71ae5a4SJacob Faibussowitsch       break;
106385385478SLisandro Dalcin     }
106485385478SLisandro Dalcin   }
106585385478SLisandro Dalcin 
10669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10679566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1068fdacfa88SPeter Brune 
10699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10709566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1071186905e3SBarry Smith 
107285385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
107385385478SLisandro Dalcin 
10749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1075186905e3SBarry Smith 
10760f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10770f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1078a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1079186905e3SBarry Smith 
108090d69ab7SBarry Smith   flg = PETSC_FALSE;
10819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10829566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1083eabae89aSBarry Smith 
10849566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10859566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10869566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1087eabae89aSBarry Smith 
10889566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10899566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10909566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10919566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10929566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10939566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10949566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10962db13446SMatthew G. Knepley 
10979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10989566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10995180491cSLisandro Dalcin 
110090d69ab7SBarry Smith   flg = PETSC_FALSE;
11019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1102459f5d12SBarry Smith   if (flg) {
1103459f5d12SBarry Smith     PetscViewer ctx;
1104e24b481bSBarry Smith 
11059566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
11069566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1107459f5d12SBarry Smith   }
11082e7541e6SPeter Brune 
1109648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1110648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
111190d69ab7SBarry Smith   flg = PETSC_FALSE;
11129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
11139566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1114c4421ceaSFande Kong 
1115c4421ceaSFande Kong   flg = PETSC_FALSE;
11169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
11174b27c08aSLois Curfman McInnes   if (flg) {
11186cab3a1bSJed Brown     void *functx;
1119b1f624c7SBarry Smith     DM    dm;
11209566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1121800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11229566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
11239566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
11249566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11259b94acceSBarry Smith   }
1126639f9d9dSBarry Smith 
112744848bc4SPeter Brune   flg = PETSC_FALSE;
11289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11291baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
113097584545SPeter Brune 
113197584545SPeter Brune   flg = PETSC_FALSE;
11329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
113344848bc4SPeter Brune   if (flg) {
1134c52e227fSPeter Brune     DM dm;
11359566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1136800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11379566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11389566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
113944848bc4SPeter Brune   }
114044848bc4SPeter Brune 
1141aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1143d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1144a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1145d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1146a8248277SBarry Smith   }
1147aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1149d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1151d28543b3SPeter Brune 
1152c40d0f55SPeter Brune   flg = PETSC_FALSE;
11539566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11559566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1156c40d0f55SPeter Brune 
1157e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11588a70d858SHong Zhang   /*
11598a70d858SHong Zhang     Publish convergence information using SAWs
11608a70d858SHong Zhang   */
11618a70d858SHong Zhang   flg = PETSC_FALSE;
11629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11638a70d858SHong Zhang   if (flg) {
11648a70d858SHong Zhang     void *ctx;
11659566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11669566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11678a70d858SHong Zhang   }
11688a70d858SHong Zhang #endif
11698a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1170b90c6cbeSBarry Smith   {
1171b90c6cbeSBarry Smith     PetscBool set;
1172b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11741baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1175b90c6cbeSBarry Smith   }
1176b90c6cbeSBarry Smith #endif
1177b90c6cbeSBarry Smith 
117848a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
117976b2cf59SMatthew Knepley 
1180dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11815d973c19SBarry Smith 
11825d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1183dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1184d0609cedSBarry Smith   PetscOptionsEnd();
11854bbc92c1SBarry Smith 
1186d8d34be6SBarry Smith   if (snes->linesearch) {
11879566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11889566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1189d8d34be6SBarry Smith   }
11909e764e56SPeter Brune 
11916aa5e7e9SBarry Smith   if (snes->usesksp) {
11929566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11939566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11949566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11956aa5e7e9SBarry Smith   }
11966991f827SBarry Smith 
1197b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11989566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
120048a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
12011baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1202b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
12033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1204b3cd9a81SMatthew G. Knepley }
1205b3cd9a81SMatthew G. Knepley 
1206b3cd9a81SMatthew G. Knepley /*@
1207420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1208b3cd9a81SMatthew G. Knepley 
1209c3339decSBarry Smith   Collective
1210b3cd9a81SMatthew G. Knepley 
1211b3cd9a81SMatthew G. Knepley   Input Parameter:
1212f6dfbefdSBarry Smith . snes - the `SNES` context
1213b3cd9a81SMatthew G. Knepley 
1214420bcc1bSBarry Smith   Level: advanced
1215b3cd9a81SMatthew G. Knepley 
12161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1217b3cd9a81SMatthew G. Knepley @*/
1218d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1219d71ae5a4SJacob Faibussowitsch {
1220b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
12219566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12239b94acceSBarry Smith }
12249b94acceSBarry Smith 
1225bb9467b5SJed Brown /*@C
1226d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1227d25893d9SBarry Smith   the nonlinear solvers.
1228d25893d9SBarry Smith 
1229dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1230d25893d9SBarry Smith 
1231d25893d9SBarry Smith   Input Parameters:
1232f6dfbefdSBarry Smith + snes    - the `SNES` context
1233d25893d9SBarry Smith . compute - function to compute the context
1234d25893d9SBarry Smith - destroy - function to destroy the context
1235d25893d9SBarry Smith 
1236420bcc1bSBarry Smith   Calling sequence of `compute`:
1237420bcc1bSBarry Smith + snes - the `SNES` context
1238420bcc1bSBarry Smith - ctx  - context to be computed
1239420bcc1bSBarry Smith 
1240420bcc1bSBarry Smith   Calling sequence of `destroy`:
1241420bcc1bSBarry Smith . ctx - context to be computed by `compute()`
1242420bcc1bSBarry Smith 
1243d25893d9SBarry Smith   Level: intermediate
1244d25893d9SBarry Smith 
1245f6dfbefdSBarry Smith   Note:
1246f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1247f6dfbefdSBarry Smith 
1248f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1249f6dfbefdSBarry Smith 
125042747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`
1251d25893d9SBarry Smith @*/
1252420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx))
1253d71ae5a4SJacob Faibussowitsch {
1254d25893d9SBarry Smith   PetscFunctionBegin;
1255d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1256d25893d9SBarry Smith   snes->ops->usercompute = compute;
1257d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
12583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1259d25893d9SBarry Smith }
1260a847f771SSatish Balay 
1261b07ff414SBarry Smith /*@
1262f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12639b94acceSBarry Smith 
1264c3339decSBarry Smith   Logically Collective
1265fee21e36SBarry Smith 
1266c7afd0dbSLois Curfman McInnes   Input Parameters:
1267f6dfbefdSBarry Smith + snes - the `SNES` context
1268c7afd0dbSLois Curfman McInnes - usrP - optional user context
1269c7afd0dbSLois Curfman McInnes 
127036851e7fSLois Curfman McInnes   Level: intermediate
127136851e7fSLois Curfman McInnes 
1272f6dfbefdSBarry Smith   Notes:
1273f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1274f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1275f6dfbefdSBarry Smith 
1276f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1277f6dfbefdSBarry Smith 
1278420bcc1bSBarry Smith   Fortran Note:
1279dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1280420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1281daf670e6SBarry Smith 
12821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12839b94acceSBarry Smith @*/
1284d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1285d71ae5a4SJacob Faibussowitsch {
1286b07ff414SBarry Smith   KSP ksp;
12871b2093e4SBarry Smith 
12883a40ed3dSBarry Smith   PetscFunctionBegin;
12890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12909566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12919566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12929b94acceSBarry Smith   snes->user = usrP;
12933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12949b94acceSBarry Smith }
129574679c65SBarry Smith 
1296b07ff414SBarry Smith /*@
12979b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1298420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12999b94acceSBarry Smith 
1300c7afd0dbSLois Curfman McInnes   Not Collective
1301c7afd0dbSLois Curfman McInnes 
13029b94acceSBarry Smith   Input Parameter:
1303f6dfbefdSBarry Smith . snes - `SNES` context
13049b94acceSBarry Smith 
13059b94acceSBarry Smith   Output Parameter:
13069b94acceSBarry Smith . usrP - user context
13079b94acceSBarry Smith 
130836851e7fSLois Curfman McInnes   Level: intermediate
130936851e7fSLois Curfman McInnes 
1310420bcc1bSBarry Smith   Fortran Note:
1311dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1312420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1313dc4c0fb0SBarry Smith 
1314420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13159b94acceSBarry Smith @*/
1316d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1317d71ae5a4SJacob Faibussowitsch {
13183a40ed3dSBarry Smith   PetscFunctionBegin;
13190700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1320e71120c6SJed Brown   *(void **)usrP = snes->user;
13213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13229b94acceSBarry Smith }
132374679c65SBarry Smith 
13249b94acceSBarry Smith /*@
1325420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13263565c898SBarry Smith 
1327dc4c0fb0SBarry Smith   Logically Collective
13283565c898SBarry Smith 
13293565c898SBarry Smith   Input Parameters:
1330f6dfbefdSBarry Smith + snes        - `SNES` context
1331f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1332f6dfbefdSBarry 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
1333420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13343565c898SBarry Smith 
1335f6dfbefdSBarry Smith   Options Database Keys:
133601c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1337f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1338ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1339ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13403565c898SBarry Smith 
13413565c898SBarry Smith   Level: intermediate
13423565c898SBarry Smith 
1343f6dfbefdSBarry Smith   Note:
1344420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1345420bcc1bSBarry Smith   and computing explicitly with
1346f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1347ec5066bdSBarry Smith 
1348420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13493565c898SBarry Smith @*/
1350d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1351d71ae5a4SJacob Faibussowitsch {
13523565c898SBarry Smith   PetscFunctionBegin;
13533565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
135488b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
135588b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13564ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13573565c898SBarry Smith   snes->mf_operator = mf_operator;
13583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13593565c898SBarry Smith }
13603565c898SBarry Smith 
13613565c898SBarry Smith /*@
1362dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13633565c898SBarry Smith 
1364420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13653565c898SBarry Smith 
13663565c898SBarry Smith   Input Parameter:
1367f6dfbefdSBarry Smith . snes - `SNES` context
13683565c898SBarry Smith 
13693565c898SBarry Smith   Output Parameters:
1370f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1371f6dfbefdSBarry 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
13723565c898SBarry Smith 
13733565c898SBarry Smith   Level: intermediate
13743565c898SBarry Smith 
13751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13763565c898SBarry Smith @*/
1377d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1378d71ae5a4SJacob Faibussowitsch {
13793565c898SBarry Smith   PetscFunctionBegin;
13803565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13813565c898SBarry Smith   if (mf) *mf = snes->mf;
13823565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13843565c898SBarry Smith }
13853565c898SBarry Smith 
13863565c898SBarry Smith /*@
1387420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13889b94acceSBarry Smith 
1389c7afd0dbSLois Curfman McInnes   Not Collective
1390c7afd0dbSLois Curfman McInnes 
13919b94acceSBarry Smith   Input Parameter:
1392f6dfbefdSBarry Smith . snes - `SNES` context
13939b94acceSBarry Smith 
13949b94acceSBarry Smith   Output Parameter:
13959b94acceSBarry Smith . iter - iteration number
13969b94acceSBarry Smith 
1397dc4c0fb0SBarry Smith   Level: intermediate
1398dc4c0fb0SBarry Smith 
1399c8228a4eSBarry Smith   Notes:
1400c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1401c8228a4eSBarry Smith 
1402c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1403f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
140408405cd6SLois Curfman McInnes .vb
140508405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
140608405cd6SLois Curfman McInnes       if (!(it % 2)) {
140708405cd6SLois Curfman McInnes         [compute Jacobian here]
140808405cd6SLois Curfman McInnes       }
140908405cd6SLois Curfman McInnes .ve
1410f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1411f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1412c8228a4eSBarry Smith 
1413f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1414c04deec6SBarry Smith 
1415420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14169b94acceSBarry Smith @*/
1417d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1418d71ae5a4SJacob Faibussowitsch {
14193a40ed3dSBarry Smith   PetscFunctionBegin;
14200700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14214f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14229b94acceSBarry Smith   *iter = snes->iter;
14233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14249b94acceSBarry Smith }
142574679c65SBarry Smith 
1426360c497dSPeter Brune /*@
1427360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1428360c497dSPeter Brune 
1429360c497dSPeter Brune   Not Collective
1430360c497dSPeter Brune 
1431d8d19677SJose E. Roman   Input Parameters:
1432f6dfbefdSBarry Smith + snes - `SNES` context
1433a2b725a8SWilliam Gropp - iter - iteration number
1434360c497dSPeter Brune 
1435360c497dSPeter Brune   Level: developer
1436360c497dSPeter Brune 
1437420bcc1bSBarry Smith   Note:
1438420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1439420bcc1bSBarry Smith 
14401cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1441360c497dSPeter Brune @*/
1442d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1443d71ae5a4SJacob Faibussowitsch {
1444360c497dSPeter Brune   PetscFunctionBegin;
1445360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14469566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1447360c497dSPeter Brune   snes->iter = iter;
14489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1450360c497dSPeter Brune }
1451360c497dSPeter Brune 
14529b94acceSBarry Smith /*@
1453b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1454420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14559b94acceSBarry Smith 
1456c7afd0dbSLois Curfman McInnes   Not Collective
1457c7afd0dbSLois Curfman McInnes 
14589b94acceSBarry Smith   Input Parameter:
1459f6dfbefdSBarry Smith . snes - `SNES` context
14609b94acceSBarry Smith 
14619b94acceSBarry Smith   Output Parameter:
14629b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14639b94acceSBarry Smith 
1464dc4c0fb0SBarry Smith   Level: intermediate
1465dc4c0fb0SBarry Smith 
1466f6dfbefdSBarry Smith   Note:
1467f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1468c96a6f78SLois Curfman McInnes 
14691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1470db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14719b94acceSBarry Smith @*/
1472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1473d71ae5a4SJacob Faibussowitsch {
14743a40ed3dSBarry Smith   PetscFunctionBegin;
14750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14764f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
147750ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147950ffb88aSMatthew Knepley }
148050ffb88aSMatthew Knepley 
148150ffb88aSMatthew Knepley /*@
1482b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1483420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
148450ffb88aSMatthew Knepley 
148550ffb88aSMatthew Knepley   Not Collective
148650ffb88aSMatthew Knepley 
148750ffb88aSMatthew Knepley   Input Parameters:
1488f6dfbefdSBarry Smith + snes     - `SNES` context
148977e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
149050ffb88aSMatthew Knepley 
1491420bcc1bSBarry Smith   Options Database Key:
1492420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1493420bcc1bSBarry Smith 
149450ffb88aSMatthew Knepley   Level: intermediate
149550ffb88aSMatthew Knepley 
1496420bcc1bSBarry Smith   Developer Note:
1497420bcc1bSBarry Smith   The options database key is wrong for this function name
1498420bcc1bSBarry Smith 
14991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1500db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
150150ffb88aSMatthew Knepley @*/
1502d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1503d71ae5a4SJacob Faibussowitsch {
150450ffb88aSMatthew Knepley   PetscFunctionBegin;
15050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
150677e5a1f9SBarry Smith 
150777e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
150877e5a1f9SBarry Smith     snes->maxFailures = PETSC_MAX_INT;
150977e5a1f9SBarry Smith   } else {
151077e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
151150ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
151277e5a1f9SBarry Smith   }
15133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151450ffb88aSMatthew Knepley }
151550ffb88aSMatthew Knepley 
151650ffb88aSMatthew Knepley /*@
1517b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1518420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
151950ffb88aSMatthew Knepley 
152050ffb88aSMatthew Knepley   Not Collective
152150ffb88aSMatthew Knepley 
152250ffb88aSMatthew Knepley   Input Parameter:
152320f4b53cSBarry Smith . snes - `SNES` context
152450ffb88aSMatthew Knepley 
152550ffb88aSMatthew Knepley   Output Parameter:
152650ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
152750ffb88aSMatthew Knepley 
152850ffb88aSMatthew Knepley   Level: intermediate
152950ffb88aSMatthew Knepley 
15301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1531db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
153250ffb88aSMatthew Knepley @*/
1533d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1534d71ae5a4SJacob Faibussowitsch {
153550ffb88aSMatthew Knepley   PetscFunctionBegin;
15360700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15374f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
153850ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15409b94acceSBarry Smith }
1541a847f771SSatish Balay 
15422541af92SBarry Smith /*@
15432541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1544420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15452541af92SBarry Smith 
15462541af92SBarry Smith   Not Collective
15472541af92SBarry Smith 
15482541af92SBarry Smith   Input Parameter:
1549f6dfbefdSBarry Smith . snes - `SNES` context
15502541af92SBarry Smith 
15512541af92SBarry Smith   Output Parameter:
15522541af92SBarry Smith . nfuncs - number of evaluations
15532541af92SBarry Smith 
15542541af92SBarry Smith   Level: intermediate
15552541af92SBarry Smith 
1556f6dfbefdSBarry Smith   Note:
1557f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1558971e163fSPeter Brune 
15591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15602541af92SBarry Smith @*/
1561d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1562d71ae5a4SJacob Faibussowitsch {
15632541af92SBarry Smith   PetscFunctionBegin;
15640700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15654f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15662541af92SBarry Smith   *nfuncs = snes->nfuncs;
15673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15682541af92SBarry Smith }
15692541af92SBarry Smith 
15703d4c4710SBarry Smith /*@
15713d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1572420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15733d4c4710SBarry Smith 
15743d4c4710SBarry Smith   Not Collective
15753d4c4710SBarry Smith 
15763d4c4710SBarry Smith   Input Parameter:
1577f6dfbefdSBarry Smith . snes - `SNES` context
15783d4c4710SBarry Smith 
15793d4c4710SBarry Smith   Output Parameter:
15803d4c4710SBarry Smith . nfails - number of failed solves
15813d4c4710SBarry Smith 
1582f6dfbefdSBarry Smith   Options Database Key:
15839d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15849d85da0cSMatthew G. Knepley 
1585f6dfbefdSBarry Smith   Level: intermediate
1586f6dfbefdSBarry Smith 
1587f6dfbefdSBarry Smith   Note:
1588f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15893d4c4710SBarry Smith 
15901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15913d4c4710SBarry Smith @*/
1592d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1593d71ae5a4SJacob Faibussowitsch {
15943d4c4710SBarry Smith   PetscFunctionBegin;
15950700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15964f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15973d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15993d4c4710SBarry Smith }
16003d4c4710SBarry Smith 
16013d4c4710SBarry Smith /*@
16023d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1603f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
16043d4c4710SBarry Smith 
1605c3339decSBarry Smith   Logically Collective
16063d4c4710SBarry Smith 
16073d4c4710SBarry Smith   Input Parameters:
1608f6dfbefdSBarry Smith + snes     - `SNES` context
160977e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16103d4c4710SBarry Smith 
1611f6dfbefdSBarry Smith   Options Database Key:
16129d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16139d85da0cSMatthew G. Knepley 
1614dc4c0fb0SBarry Smith   Level: intermediate
1615dc4c0fb0SBarry Smith 
1616f6dfbefdSBarry Smith   Note:
1617f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16183d4c4710SBarry Smith 
1619420bcc1bSBarry Smith   Developer Note:
1620420bcc1bSBarry Smith   The options database key is wrong for this function name
1621420bcc1bSBarry Smith 
16221cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16233d4c4710SBarry Smith @*/
1624d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1625d71ae5a4SJacob Faibussowitsch {
16263d4c4710SBarry Smith   PetscFunctionBegin;
16270700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1628c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
162977e5a1f9SBarry Smith 
163077e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
163177e5a1f9SBarry Smith     snes->maxLinearSolveFailures = PETSC_MAX_INT;
163277e5a1f9SBarry Smith   } else {
163377e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16343d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
163577e5a1f9SBarry Smith   }
16363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16373d4c4710SBarry Smith }
16383d4c4710SBarry Smith 
16393d4c4710SBarry Smith /*@
16403d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1641f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16423d4c4710SBarry Smith 
16433d4c4710SBarry Smith   Not Collective
16443d4c4710SBarry Smith 
16453d4c4710SBarry Smith   Input Parameter:
1646f6dfbefdSBarry Smith . snes - `SNES` context
16473d4c4710SBarry Smith 
16483d4c4710SBarry Smith   Output Parameter:
16493d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16503d4c4710SBarry Smith 
16513d4c4710SBarry Smith   Level: intermediate
16523d4c4710SBarry Smith 
1653f6dfbefdSBarry Smith   Note:
1654f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16553d4c4710SBarry Smith 
16561cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16573d4c4710SBarry Smith @*/
1658d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1659d71ae5a4SJacob Faibussowitsch {
16603d4c4710SBarry Smith   PetscFunctionBegin;
16610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16624f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16633d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16653d4c4710SBarry Smith }
16663d4c4710SBarry Smith 
1667c96a6f78SLois Curfman McInnes /*@
1668b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1669420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1670c96a6f78SLois Curfman McInnes 
1671c7afd0dbSLois Curfman McInnes   Not Collective
1672c7afd0dbSLois Curfman McInnes 
1673c96a6f78SLois Curfman McInnes   Input Parameter:
1674f6dfbefdSBarry Smith . snes - `SNES` context
1675c96a6f78SLois Curfman McInnes 
1676c96a6f78SLois Curfman McInnes   Output Parameter:
1677c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1678c96a6f78SLois Curfman McInnes 
1679dc4c0fb0SBarry Smith   Level: intermediate
1680dc4c0fb0SBarry Smith 
1681c96a6f78SLois Curfman McInnes   Notes:
1682f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1683c96a6f78SLois Curfman McInnes 
1684f6dfbefdSBarry 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
1685f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1686010be392SBarry Smith 
16871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1688c96a6f78SLois Curfman McInnes @*/
1689d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1690d71ae5a4SJacob Faibussowitsch {
16913a40ed3dSBarry Smith   PetscFunctionBegin;
16920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16934f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1694c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1696c96a6f78SLois Curfman McInnes }
1697c96a6f78SLois Curfman McInnes 
1698971e163fSPeter Brune /*@
1699971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1700f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1701971e163fSPeter Brune 
1702c3339decSBarry Smith   Logically Collective
1703971e163fSPeter Brune 
1704d8d19677SJose E. Roman   Input Parameters:
1705f6dfbefdSBarry Smith + snes  - `SNES` context
1706f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1707971e163fSPeter Brune 
1708971e163fSPeter Brune   Level: developer
1709971e163fSPeter Brune 
17101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1711971e163fSPeter Brune @*/
1712d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1713d71ae5a4SJacob Faibussowitsch {
1714971e163fSPeter Brune   PetscFunctionBegin;
1715971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1716971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1717971e163fSPeter Brune   snes->counters_reset = reset;
17183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1719971e163fSPeter Brune }
1720971e163fSPeter Brune 
17212999313aSBarry Smith /*@
1722f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17232999313aSBarry Smith 
1724420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17252999313aSBarry Smith 
17262999313aSBarry Smith   Input Parameters:
1727f6dfbefdSBarry Smith + snes - the `SNES` context
1728f6dfbefdSBarry Smith - ksp  - the `KSP` context
17292999313aSBarry Smith 
1730dc4c0fb0SBarry Smith   Level: developer
1731dc4c0fb0SBarry Smith 
17322999313aSBarry Smith   Notes:
1733f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17342999313aSBarry Smith   so this routine is rarely needed.
17352999313aSBarry Smith 
1736f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1737420bcc1bSBarry Smith   decreased by one when this is called.
17382999313aSBarry Smith 
173942747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17402999313aSBarry Smith @*/
1741d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1742d71ae5a4SJacob Faibussowitsch {
17432999313aSBarry Smith   PetscFunctionBegin;
17440700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17450700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17462999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17479566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17489566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17492999313aSBarry Smith   snes->ksp = ksp;
17503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17512999313aSBarry Smith }
17522999313aSBarry Smith 
175352baeb72SSatish Balay /*@
175477e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
175577e5a1f9SBarry Smith   currently contain default values
175677e5a1f9SBarry Smith 
175777e5a1f9SBarry Smith   Collective
175877e5a1f9SBarry Smith 
175977e5a1f9SBarry Smith   Input Parameter:
176077e5a1f9SBarry Smith . snes - the `SNES` object
176177e5a1f9SBarry Smith 
176277e5a1f9SBarry Smith   Level: developer
176377e5a1f9SBarry Smith 
176477e5a1f9SBarry Smith   Developer Note:
176577e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
176677e5a1f9SBarry Smith 
176777e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
176877e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
176977e5a1f9SBarry Smith @*/
177077e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
177177e5a1f9SBarry Smith {
177277e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
177377e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
177477e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
177577e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
177677e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
177777e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
177877e5a1f9SBarry Smith   return PETSC_SUCCESS;
177977e5a1f9SBarry Smith }
178077e5a1f9SBarry Smith 
178177e5a1f9SBarry Smith /*@
1782dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
17839b94acceSBarry Smith 
1784d083f849SBarry Smith   Collective
1785c7afd0dbSLois Curfman McInnes 
1786f6dfbefdSBarry Smith   Input Parameter:
1787906ed7ccSBarry Smith . comm - MPI communicator
17889b94acceSBarry Smith 
17899b94acceSBarry Smith   Output Parameter:
179020f4b53cSBarry Smith . outsnes - the new `SNES` context
17919b94acceSBarry Smith 
1792c7afd0dbSLois Curfman McInnes   Options Database Keys:
1793dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1794dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1795dc4c0fb0SBarry Smith                       as set by `SNESSetJacobian()`
1796dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1797c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1798c1f60f51SBarry Smith 
179936851e7fSLois Curfman McInnes   Level: beginner
180036851e7fSLois Curfman McInnes 
180195452b02SPatrick Sanan   Developer Notes:
1802f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1803efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1804f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1805f6dfbefdSBarry Smith   in `SNESView()`.
1806efd4aadfSBarry Smith 
1807f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1808f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1809f6dfbefdSBarry Smith 
1810dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1811efd4aadfSBarry Smith 
1812e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18139b94acceSBarry Smith @*/
1814d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1815d71ae5a4SJacob Faibussowitsch {
18169b94acceSBarry Smith   SNES       snes;
1817fa9f3622SBarry Smith   SNESKSPEW *kctx;
181837fcc0dbSBarry Smith 
18193a40ed3dSBarry Smith   PetscFunctionBegin;
18204f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18219566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18228ba1e511SMatthew Knepley 
18239566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18248d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18252c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18269b94acceSBarry Smith   snes->norm           = 0.0;
1827c1e67a49SFande Kong   snes->xnorm          = 0.0;
1828c1e67a49SFande Kong   snes->ynorm          = 0.0;
1829365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18306c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1831b4874afaSBarry Smith   snes->ttol           = 0.0;
183277e5a1f9SBarry Smith 
1833e37c518bSBarry Smith   snes->rnorm0               = 0;
18349b94acceSBarry Smith   snes->nfuncs               = 0;
183550ffb88aSMatthew Knepley   snes->numFailures          = 0;
183650ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18377a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1838e35cf81dSBarry Smith   snes->lagjacobian          = 1;
183937ec4e1aSPeter Brune   snes->jac_iter             = 0;
184037ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1841a8054027SBarry Smith   snes->lagpreconditioner    = 1;
184237ec4e1aSPeter Brune   snes->pre_iter             = 0;
184337ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1844639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1845c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18469e5d0892SLisandro Dalcin   snes->data                 = NULL;
18474dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1848186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18496f24a144SLois Curfman McInnes   snes->nwork                = 0;
18509e5d0892SLisandro Dalcin   snes->work                 = NULL;
185158c9b817SLisandro Dalcin   snes->nvwork               = 0;
18529e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1853758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1854758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18550298fd71SBarry Smith   snes->conv_hist            = NULL;
18560298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1857758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1858971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1859e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1860184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1861efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1862b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1863c40d0f55SPeter Brune 
1864d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1865d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1866d8f46077SPeter Brune   snes->mf_version  = 1;
1867d8f46077SPeter Brune 
18683d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18693d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18703d4c4710SBarry Smith 
1871349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
187276bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1873349187a7SBarry Smith 
18744fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18754fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
18764fc747eaSLawrence Mitchell 
18779b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18784dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1879f5af7f23SKarl Rupp 
18809b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
18819b94acceSBarry Smith   kctx->version     = 2;
18820f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
18839b94acceSBarry Smith                              this was too large for some test cases */
188475567043SBarry Smith   kctx->rtol_last   = 0.0;
18850f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
18869b94acceSBarry Smith   kctx->gamma       = 1.0;
18870f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
188871f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
18890f0abf79SStefano Zampini   kctx->threshold   = 0.1;
189075567043SBarry Smith   kctx->lresid_last = 0.0;
189175567043SBarry Smith   kctx->norm_last   = 0.0;
18929b94acceSBarry Smith 
18930f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
18940f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
18950f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
18960f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
18970f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
18980f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
18990f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19000f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19010f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19020f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19030f0abf79SStefano Zampini 
19049b94acceSBarry Smith   *outsnes = snes;
19053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19069b94acceSBarry Smith }
19079b94acceSBarry Smith 
19089b94acceSBarry Smith /*@C
19099b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1910f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19119b94acceSBarry Smith   equations.
19129b94acceSBarry Smith 
1913c3339decSBarry Smith   Logically Collective
1914fee21e36SBarry Smith 
1915c7afd0dbSLois Curfman McInnes   Input Parameters:
1916f6dfbefdSBarry Smith + snes - the `SNES` context
1917dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19188434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1919c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1920dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19219b94acceSBarry Smith 
192236851e7fSLois Curfman McInnes   Level: beginner
192336851e7fSLois Curfman McInnes 
19248434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19259b94acceSBarry Smith @*/
19268434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1927d71ae5a4SJacob Faibussowitsch {
19286cab3a1bSJed Brown   DM dm;
19296cab3a1bSJed Brown 
19303a40ed3dSBarry Smith   PetscFunctionBegin;
19310700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1932d2a683ecSLisandro Dalcin   if (r) {
1933d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1934d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19359566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19369566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
193785385478SLisandro Dalcin     snes->vec_func = r;
1938d2a683ecSLisandro Dalcin   }
19399566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19409566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
194148a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19439b94acceSBarry Smith }
19449b94acceSBarry Smith 
1945e4ed7901SPeter Brune /*@C
19460b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1947e4ed7901SPeter Brune 
1948c3339decSBarry Smith   Logically Collective
1949e4ed7901SPeter Brune 
1950e4ed7901SPeter Brune   Input Parameters:
1951f6dfbefdSBarry Smith + snes - the `SNES` context
1952e4ed7901SPeter Brune - f    - vector to store function value
1953e4ed7901SPeter Brune 
1954dc4c0fb0SBarry Smith   Level: developer
1955dc4c0fb0SBarry Smith 
1956e4ed7901SPeter Brune   Notes:
1957e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1958e4ed7901SPeter Brune 
1959f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1960e4ed7901SPeter Brune 
19611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1962e4ed7901SPeter Brune @*/
1963d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1964d71ae5a4SJacob Faibussowitsch {
1965e4ed7901SPeter Brune   Vec vec_func;
1966e4ed7901SPeter Brune 
1967e4ed7901SPeter Brune   PetscFunctionBegin;
1968e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1969e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1970e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1971efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1972902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19733ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1974902f982fSPeter Brune   }
19759566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19769566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1977f5af7f23SKarl Rupp 
1978217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1980e4ed7901SPeter Brune }
1981e4ed7901SPeter Brune 
1982534ebe21SPeter Brune /*@
1983f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1984f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1985534ebe21SPeter Brune 
1986c3339decSBarry Smith   Logically Collective
1987534ebe21SPeter Brune 
1988534ebe21SPeter Brune   Input Parameters:
1989f6dfbefdSBarry Smith + snes         - the `SNES` context
1990365a6726SPeter Brune - normschedule - the frequency of norm computation
1991534ebe21SPeter Brune 
1992517f1916SMatthew G. Knepley   Options Database Key:
199367b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1994517f1916SMatthew G. Knepley 
1995dc4c0fb0SBarry Smith   Level: advanced
1996dc4c0fb0SBarry Smith 
1997534ebe21SPeter Brune   Notes:
1998f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1999534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2000534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2001f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2002534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2003534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2004534ebe21SPeter Brune   their solution.
2005534ebe21SPeter Brune 
2006e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2007534ebe21SPeter Brune @*/
2008d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2009d71ae5a4SJacob Faibussowitsch {
2010534ebe21SPeter Brune   PetscFunctionBegin;
2011534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2012365a6726SPeter Brune   snes->normschedule = normschedule;
20133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2014534ebe21SPeter Brune }
2015534ebe21SPeter Brune 
2016534ebe21SPeter Brune /*@
2017f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2018f6dfbefdSBarry Smith   of the `SNES` method.
2019534ebe21SPeter Brune 
2020c3339decSBarry Smith   Logically Collective
2021534ebe21SPeter Brune 
2022534ebe21SPeter Brune   Input Parameters:
2023f6dfbefdSBarry Smith + snes         - the `SNES` context
2024365a6726SPeter Brune - normschedule - the type of the norm used
2025534ebe21SPeter Brune 
2026534ebe21SPeter Brune   Level: advanced
2027534ebe21SPeter Brune 
20281cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2029534ebe21SPeter Brune @*/
2030d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2031d71ae5a4SJacob Faibussowitsch {
2032534ebe21SPeter Brune   PetscFunctionBegin;
2033534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2034365a6726SPeter Brune   *normschedule = snes->normschedule;
20353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2036534ebe21SPeter Brune }
2037534ebe21SPeter Brune 
2038c5ce4427SMatthew G. Knepley /*@
2039c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2040c5ce4427SMatthew G. Knepley 
2041c3339decSBarry Smith   Logically Collective
2042c5ce4427SMatthew G. Knepley 
2043c5ce4427SMatthew G. Knepley   Input Parameters:
2044f6dfbefdSBarry Smith + snes - the `SNES` context
2045f6dfbefdSBarry Smith - norm - the value of the norm
2046c5ce4427SMatthew G. Knepley 
2047c5ce4427SMatthew G. Knepley   Level: developer
2048c5ce4427SMatthew G. Knepley 
20491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2050c5ce4427SMatthew G. Knepley @*/
2051d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2052d71ae5a4SJacob Faibussowitsch {
2053c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2054c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2055c5ce4427SMatthew G. Knepley   snes->norm = norm;
20563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2057c5ce4427SMatthew G. Knepley }
2058c5ce4427SMatthew G. Knepley 
2059c5ce4427SMatthew G. Knepley /*@
2060c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2061c5ce4427SMatthew G. Knepley 
2062c5ce4427SMatthew G. Knepley   Not Collective
2063c5ce4427SMatthew G. Knepley 
2064c5ce4427SMatthew G. Knepley   Input Parameter:
2065f6dfbefdSBarry Smith . snes - the `SNES` context
2066c5ce4427SMatthew G. Knepley 
2067c5ce4427SMatthew G. Knepley   Output Parameter:
2068c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2069c5ce4427SMatthew G. Knepley 
2070c5ce4427SMatthew G. Knepley   Level: developer
2071c5ce4427SMatthew G. Knepley 
20721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2073c5ce4427SMatthew G. Knepley @*/
2074d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2075d71ae5a4SJacob Faibussowitsch {
2076c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2077c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20784f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2079c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2081c5ce4427SMatthew G. Knepley }
2082c5ce4427SMatthew G. Knepley 
2083c1e67a49SFande Kong /*@
2084f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2085c1e67a49SFande Kong 
2086c1e67a49SFande Kong   Not Collective
2087c1e67a49SFande Kong 
2088c1e67a49SFande Kong   Input Parameter:
2089f6dfbefdSBarry Smith . snes - the `SNES` context
2090c1e67a49SFande Kong 
2091c1e67a49SFande Kong   Output Parameter:
2092c1e67a49SFande Kong . ynorm - the last computed update norm
2093c1e67a49SFande Kong 
2094c1e67a49SFande Kong   Level: developer
2095c1e67a49SFande Kong 
2096f6dfbefdSBarry Smith   Note:
2097f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2098f6dfbefdSBarry Smith 
20991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2100c1e67a49SFande Kong @*/
2101d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2102d71ae5a4SJacob Faibussowitsch {
2103c1e67a49SFande Kong   PetscFunctionBegin;
2104c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21054f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2106c1e67a49SFande Kong   *ynorm = snes->ynorm;
21073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2108c1e67a49SFande Kong }
2109c1e67a49SFande Kong 
2110c1e67a49SFande Kong /*@
21114591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2112c1e67a49SFande Kong 
2113c1e67a49SFande Kong   Not Collective
2114c1e67a49SFande Kong 
2115c1e67a49SFande Kong   Input Parameter:
2116f6dfbefdSBarry Smith . snes - the `SNES` context
2117c1e67a49SFande Kong 
2118c1e67a49SFande Kong   Output Parameter:
2119c1e67a49SFande Kong . xnorm - the last computed solution norm
2120c1e67a49SFande Kong 
2121c1e67a49SFande Kong   Level: developer
2122c1e67a49SFande Kong 
21231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2124c1e67a49SFande Kong @*/
2125d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2126d71ae5a4SJacob Faibussowitsch {
2127c1e67a49SFande Kong   PetscFunctionBegin;
2128c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21294f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2130c1e67a49SFande Kong   *xnorm = snes->xnorm;
21313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2132c1e67a49SFande Kong }
2133c1e67a49SFande Kong 
2134cc4c1da9SBarry Smith /*@
2135f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2136f6dfbefdSBarry Smith   of the `SNES` method.
213747073ea2SPeter Brune 
2138c3339decSBarry Smith   Logically Collective
213947073ea2SPeter Brune 
214047073ea2SPeter Brune   Input Parameters:
2141f6dfbefdSBarry Smith + snes - the `SNES` context
2142f6dfbefdSBarry Smith - type - the function type
214347073ea2SPeter Brune 
214447073ea2SPeter Brune   Level: developer
214547073ea2SPeter Brune 
2146420bcc1bSBarry Smith   Values of the function type\:
2147f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2148f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2149f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2150f6dfbefdSBarry Smith 
2151420bcc1bSBarry Smith   Note:
2152f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2153f6dfbefdSBarry Smith 
21541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
215547073ea2SPeter Brune @*/
2156d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2157d71ae5a4SJacob Faibussowitsch {
215847073ea2SPeter Brune   PetscFunctionBegin;
215947073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
216047073ea2SPeter Brune   snes->functype = type;
21613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216247073ea2SPeter Brune }
216347073ea2SPeter Brune 
2164cc4c1da9SBarry Smith /*@
2165f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
216647073ea2SPeter Brune   of the SNES method.
216747073ea2SPeter Brune 
2168c3339decSBarry Smith   Logically Collective
216947073ea2SPeter Brune 
217047073ea2SPeter Brune   Input Parameters:
2171f6dfbefdSBarry Smith + snes - the `SNES` context
2172f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
217347073ea2SPeter Brune 
217447073ea2SPeter Brune   Level: advanced
217547073ea2SPeter Brune 
21761cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
217747073ea2SPeter Brune @*/
2178d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2179d71ae5a4SJacob Faibussowitsch {
218047073ea2SPeter Brune   PetscFunctionBegin;
218147073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
218247073ea2SPeter Brune   *type = snes->functype;
21833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2184534ebe21SPeter Brune }
2185534ebe21SPeter Brune 
2186c79ef259SPeter Brune /*@C
2187be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2188c79ef259SPeter Brune   use with composed nonlinear solvers.
2189c79ef259SPeter Brune 
2190c79ef259SPeter Brune   Input Parameters:
21919bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
21928434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
219377e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2194c79ef259SPeter Brune 
2195dc4c0fb0SBarry Smith   Level: intermediate
2196dc4c0fb0SBarry Smith 
2197f6dfbefdSBarry Smith   Note:
2198f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2199f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2200c79ef259SPeter Brune 
22018434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2202c79ef259SPeter Brune @*/
22038434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2204d71ae5a4SJacob Faibussowitsch {
22056cab3a1bSJed Brown   DM dm;
22066cab3a1bSJed Brown 
2207646217ecSPeter Brune   PetscFunctionBegin;
22086cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22099566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22109566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2212646217ecSPeter Brune }
2213646217ecSPeter Brune 
2214bbc1464cSBarry Smith /*
2215bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2216bbc1464cSBarry Smith    changed during the KSPSolve()
2217bbc1464cSBarry Smith */
2218d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2219d71ae5a4SJacob Faibussowitsch {
2220bbc1464cSBarry Smith   DM     dm;
2221bbc1464cSBarry Smith   DMSNES sdm;
2222bbc1464cSBarry Smith 
2223bbc1464cSBarry Smith   PetscFunctionBegin;
22249566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22259566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2226bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2227bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2228792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22299566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22300df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2231ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2232792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22339566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2234bbc1464cSBarry Smith   } else {
2235792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22369566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2237bbc1464cSBarry Smith   }
22383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2239bbc1464cSBarry Smith }
2240bbc1464cSBarry Smith 
2241d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2242d71ae5a4SJacob Faibussowitsch {
2243e03ab78fSPeter Brune   DM     dm;
2244942e3340SBarry Smith   DMSNES sdm;
22456cab3a1bSJed Brown 
22468b0a5094SBarry Smith   PetscFunctionBegin;
22479566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22489566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22498b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2250bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2251792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22529566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2253792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22549566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2255bbc1464cSBarry Smith   } else {
2256792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22579566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2258bbc1464cSBarry Smith   }
22593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22608b0a5094SBarry Smith }
22618b0a5094SBarry Smith 
2262d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2263d71ae5a4SJacob Faibussowitsch {
22648b0a5094SBarry Smith   PetscFunctionBegin;
2265e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2266bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22679566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22689566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22708b0a5094SBarry Smith }
22718b0a5094SBarry Smith 
22728b0a5094SBarry Smith /*@C
22731d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22748b0a5094SBarry Smith 
2275c3339decSBarry Smith   Logically Collective
22768b0a5094SBarry Smith 
22778b0a5094SBarry Smith   Input Parameters:
2278f6dfbefdSBarry Smith + snes - the `SNES` context
2279dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
22808434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
22816b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2282dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
22838434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2284dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2285dc4c0fb0SBarry Smith 
2286dc4c0fb0SBarry Smith   Level: intermediate
22878b0a5094SBarry Smith 
22888b0a5094SBarry Smith   Notes:
22896b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2290f450aa47SBarry 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.
2291f450aa47SBarry Smith 
2292f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22938b0a5094SBarry Smith 
22941d27aa22SBarry 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}$.
22951d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
22968b0a5094SBarry Smith 
2297dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22988b0a5094SBarry Smith 
22990d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23001d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23018b0a5094SBarry Smith 
23028b0a5094SBarry 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
23031d27aa22SBarry 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
23041d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23058b0a5094SBarry Smith 
23061d27aa22SBarry 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
2307f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
23086b7fb656SBarry Smith 
230915229ffcSPierre 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.
23106b7fb656SBarry Smith 
2311dc4c0fb0SBarry 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
23126b7fb656SBarry 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
2313f6dfbefdSBarry 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`.
2314aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2315bbc1464cSBarry Smith 
23169bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23178434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23188b0a5094SBarry Smith @*/
23198434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2320d71ae5a4SJacob Faibussowitsch {
2321e03ab78fSPeter Brune   DM dm;
2322e03ab78fSPeter Brune 
23238b0a5094SBarry Smith   PetscFunctionBegin;
23248b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23259566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23269566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23279566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23289566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23299566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23318b0a5094SBarry Smith }
23328b0a5094SBarry Smith 
23337971a8bfSPeter Brune /*@C
23347971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23357971a8bfSPeter Brune 
2336f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23377971a8bfSPeter Brune 
23387971a8bfSPeter Brune   Input Parameter:
2339f6dfbefdSBarry Smith . snes - the `SNES` context
23407971a8bfSPeter Brune 
2341d8d19677SJose E. Roman   Output Parameters:
2342dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23438434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2344dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2345dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23468434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2347dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23487971a8bfSPeter Brune 
23497971a8bfSPeter Brune   Level: advanced
23507971a8bfSPeter Brune 
23518434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23527971a8bfSPeter Brune @*/
23538434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2354d71ae5a4SJacob Faibussowitsch {
23557971a8bfSPeter Brune   DM dm;
23567971a8bfSPeter Brune 
23577971a8bfSPeter Brune   PetscFunctionBegin;
23587971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23599566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23609566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23619566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23629566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23647971a8bfSPeter Brune }
23657971a8bfSPeter Brune 
2366d25893d9SBarry Smith /*@C
2367dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2368d25893d9SBarry Smith 
2369c3339decSBarry Smith   Logically Collective
2370d25893d9SBarry Smith 
2371d25893d9SBarry Smith   Input Parameters:
2372f6dfbefdSBarry Smith + snes - the `SNES` context
23738434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2374d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2375dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2376d25893d9SBarry Smith 
2377d25893d9SBarry Smith   Level: intermediate
2378d25893d9SBarry Smith 
23798434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2380d25893d9SBarry Smith @*/
23818434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2382d71ae5a4SJacob Faibussowitsch {
2383d25893d9SBarry Smith   PetscFunctionBegin;
2384d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2385d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2386d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2388d25893d9SBarry Smith }
2389d25893d9SBarry Smith 
23901096aae1SMatthew Knepley /*@C
2391dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2392dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
23931096aae1SMatthew Knepley 
2394c3339decSBarry Smith   Logically Collective
23951096aae1SMatthew Knepley 
23961096aae1SMatthew Knepley   Input Parameter:
2397f6dfbefdSBarry Smith . snes - the `SNES` context
23981096aae1SMatthew Knepley 
23991096aae1SMatthew Knepley   Output Parameter:
2400dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24011096aae1SMatthew Knepley 
24021096aae1SMatthew Knepley   Level: intermediate
24031096aae1SMatthew Knepley 
24041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24051096aae1SMatthew Knepley @*/
2406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2407d71ae5a4SJacob Faibussowitsch {
24081096aae1SMatthew Knepley   PetscFunctionBegin;
24090700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24104f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
241185385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24131096aae1SMatthew Knepley }
24141096aae1SMatthew Knepley 
24159b94acceSBarry Smith /*@
2416f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24179b94acceSBarry Smith 
2418c3339decSBarry Smith   Collective
2419c7afd0dbSLois Curfman McInnes 
24209b94acceSBarry Smith   Input Parameters:
2421f6dfbefdSBarry Smith + snes - the `SNES` context
2422c7afd0dbSLois Curfman McInnes - x    - input vector
24239b94acceSBarry Smith 
24249b94acceSBarry Smith   Output Parameter:
2425f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24269b94acceSBarry Smith 
2427dc4c0fb0SBarry Smith   Level: developer
2428dc4c0fb0SBarry Smith 
242900677de2SStefano Zampini   Notes:
2430f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2431bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
243236851e7fSLois Curfman McInnes 
243300677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
243400677de2SStefano Zampini 
24351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24369b94acceSBarry Smith @*/
2437d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2438d71ae5a4SJacob Faibussowitsch {
24396cab3a1bSJed Brown   DM     dm;
2440942e3340SBarry Smith   DMSNES sdm;
24419b94acceSBarry Smith 
24423a40ed3dSBarry Smith   PetscFunctionBegin;
24430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24440700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24450700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2446c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2447c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2448e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2449184914b5SBarry Smith 
24509566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24519566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24520fdf79fbSJacob 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().");
245332f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
245448a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24559566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24568ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24578ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2458800f99ffSJeremy L Thompson     {
2459800f99ffSJeremy L Thompson       void           *ctx;
24608434afd1SBarry Smith       SNESFunctionFn *computefunction;
2461800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2462800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2463800f99ffSJeremy L Thompson     }
24649566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
246548a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24660fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24679566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24680fdf79fbSJacob Faibussowitsch   }
24691baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2470ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2471422a814eSBarry Smith   /*
2472422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2473422a814eSBarry Smith      propagate the value to all processes
2474422a814eSBarry Smith   */
2475f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
24763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24779b94acceSBarry Smith }
24789b94acceSBarry Smith 
2479c79ef259SPeter Brune /*@
2480f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2481bbc1464cSBarry Smith 
2482c3339decSBarry Smith   Collective
2483bbc1464cSBarry Smith 
2484bbc1464cSBarry Smith   Input Parameters:
2485f6dfbefdSBarry Smith + snes - the `SNES` context
2486bbc1464cSBarry Smith - x    - input vector
2487bbc1464cSBarry Smith 
2488bbc1464cSBarry Smith   Output Parameter:
2489f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2490bbc1464cSBarry Smith 
2491dc4c0fb0SBarry Smith   Level: developer
2492dc4c0fb0SBarry Smith 
2493bbc1464cSBarry Smith   Notes:
2494420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2495bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2496bbc1464cSBarry Smith 
2497dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2498f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2499dd8e379bSPierre 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.
2500bbc1464cSBarry Smith 
25011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2502bbc1464cSBarry Smith @*/
2503d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2504d71ae5a4SJacob Faibussowitsch {
2505bbc1464cSBarry Smith   DM     dm;
2506bbc1464cSBarry Smith   DMSNES sdm;
2507bbc1464cSBarry Smith 
2508bbc1464cSBarry Smith   PetscFunctionBegin;
2509bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2510bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2511bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2512bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2513bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2514e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2515bbc1464cSBarry Smith 
25169566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25179566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25199566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2520bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2521bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2522792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25239566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2525bbc1464cSBarry Smith   snes->nfuncs++;
2526bbc1464cSBarry Smith   /*
2527bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2528bbc1464cSBarry Smith      propagate the value to all processes
2529bbc1464cSBarry Smith   */
2530f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2532bbc1464cSBarry Smith }
2533bbc1464cSBarry Smith 
2534bbc1464cSBarry Smith /*@
2535f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2536c79ef259SPeter Brune 
2537c3339decSBarry Smith   Collective
2538c79ef259SPeter Brune 
2539c79ef259SPeter Brune   Input Parameters:
2540f6dfbefdSBarry Smith + snes - the `SNES` context
2541c79ef259SPeter Brune . x    - input vector
2542c79ef259SPeter Brune - b    - rhs vector
2543c79ef259SPeter Brune 
2544c79ef259SPeter Brune   Output Parameter:
2545c79ef259SPeter Brune . x - new solution vector
2546c79ef259SPeter Brune 
2547dc4c0fb0SBarry Smith   Level: developer
2548dc4c0fb0SBarry Smith 
2549f6dfbefdSBarry Smith   Note:
2550f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2551c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2552c79ef259SPeter Brune   themselves.
2553c79ef259SPeter Brune 
25548434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2555c79ef259SPeter Brune @*/
2556d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2557d71ae5a4SJacob Faibussowitsch {
25586cab3a1bSJed Brown   DM     dm;
2559942e3340SBarry Smith   DMSNES sdm;
2560646217ecSPeter Brune 
2561646217ecSPeter Brune   PetscFunctionBegin;
2562646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2563064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2564064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2565064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2566064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2567e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25699566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25709566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25710fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25729566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2573792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25749566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2577646217ecSPeter Brune }
2578646217ecSPeter Brune 
2579494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2580494a190aSStefano Zampini {
2581494a190aSStefano Zampini   Vec          X;
2582494a190aSStefano Zampini   PetscScalar *g;
2583494a190aSStefano Zampini   PetscReal    f, f2;
2584494a190aSStefano Zampini   PetscInt     low, high, N, i;
2585494a190aSStefano Zampini   PetscBool    flg;
2586494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2587494a190aSStefano Zampini 
2588494a190aSStefano Zampini   PetscFunctionBegin;
2589494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2590494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2591494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2592494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2593494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2594494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2595494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2596494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2597494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2598494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2599494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2600494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2601494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2602494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2603494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2604494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2605494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2606494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2607494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2608494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2609494a190aSStefano Zampini   }
2610494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2611494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2612494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2613494a190aSStefano Zampini }
2614494a190aSStefano Zampini 
2615494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2616494a190aSStefano Zampini {
2617494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2618494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2619494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2620494a190aSStefano Zampini   PetscScalar       dot;
2621494a190aSStefano Zampini   MPI_Comm          comm;
2622494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2623494a190aSStefano Zampini   PetscViewerFormat format;
2624494a190aSStefano Zampini   PetscInt          tabs;
2625494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26268434afd1SBarry Smith   SNESObjectiveFn  *objective;
2627494a190aSStefano Zampini 
2628494a190aSStefano Zampini   PetscFunctionBegin;
2629494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2630494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2631494a190aSStefano Zampini 
2632494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2633494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2634494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2635494a190aSStefano Zampini   PetscOptionsEnd();
2636494a190aSStefano Zampini   if (!test) {
2637494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2638494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2639494a190aSStefano Zampini   }
2640494a190aSStefano Zampini 
2641494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2642494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2643494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2644494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2645494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2646494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2647494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2648494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2649494a190aSStefano Zampini   }
2650494a190aSStefano Zampini   if (!directionsprinted) {
2651494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2652494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2653494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2654494a190aSStefano Zampini   }
2655494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2656494a190aSStefano Zampini 
2657494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2658494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2659494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2660494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2661494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2662494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2663494a190aSStefano Zampini 
2664494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2665494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2666494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2667494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2668494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2669494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2670494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2671494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2672494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2673494a190aSStefano 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))));
2674494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2675494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2676494a190aSStefano Zampini 
2677494a190aSStefano Zampini   if (complete_print) {
2678494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2679494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2680494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2681494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2682494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2683494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2684494a190aSStefano Zampini   }
2685494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2686494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2687494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2688494a190aSStefano Zampini 
2689494a190aSStefano Zampini   if (complete_print) {
2690494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2691494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2692494a190aSStefano Zampini   }
2693494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2694494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2695494a190aSStefano Zampini }
2696494a190aSStefano Zampini 
2697d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2698d71ae5a4SJacob Faibussowitsch {
269912837594SBarry Smith   Mat               A, B, C, D, jacobian;
27004df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2701e885f1abSBarry Smith   PetscReal         nrm, gnorm;
270281e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27030e276705SLisandro Dalcin   MatType           mattype;
2704e885f1abSBarry Smith   PetscInt          m, n, M, N;
2705e885f1abSBarry Smith   void             *functx;
27062cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
27073325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2708e885f1abSBarry Smith   MPI_Comm          comm;
2709e885f1abSBarry Smith   PetscInt          tabs;
271012837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27113325ff46SBarry Smith   PetscViewerFormat format;
2712e885f1abSBarry Smith 
2713e885f1abSBarry Smith   PetscFunctionBegin;
2714d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
27169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27184ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27209566063dSJacob 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));
2721d0609cedSBarry Smith   PetscOptionsEnd();
27223ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2723e885f1abSBarry Smith 
27249566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27259566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27269566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27279566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27289566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
272912837594SBarry Smith   if (!complete_print && !directionsprinted) {
27309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
273212837594SBarry Smith   }
273312837594SBarry Smith   if (!directionsprinted) {
27349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
27359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
273612837594SBarry Smith     directionsprinted = PETSC_TRUE;
2737e885f1abSBarry Smith   }
27381baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2739e885f1abSBarry Smith 
27409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
274112837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
274212837594SBarry Smith   else jacobian = snes->jacobian_pre;
274312837594SBarry Smith 
27444df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
27454df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
27469566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
27474df93895SStefano Zampini 
2748a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
27499566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
27509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
27519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
275212837594SBarry Smith   while (jacobian) {
27532cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
27542cd624f9SStefano Zampini 
27552cd624f9SStefano Zampini     if (istranspose) {
27569566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
27572cd624f9SStefano Zampini       Jsave    = jacobian;
27582cd624f9SStefano Zampini       jacobian = JT;
27592cd624f9SStefano Zampini     }
27609566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
276112837594SBarry Smith     if (flg) {
276212837594SBarry Smith       A = jacobian;
27639566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
276412837594SBarry Smith     } else {
27659566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
276612837594SBarry Smith     }
2767e885f1abSBarry Smith 
27689566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
27699566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
27709566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
27719566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
27729566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
27739566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
27749566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
27759566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
27769566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2777e885f1abSBarry Smith 
27789566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
27799566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
278012837594SBarry Smith 
27819566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
27829566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
27839566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
27849566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
27859566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
278612837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
27879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
278812837594SBarry Smith 
2789e885f1abSBarry Smith     if (complete_print) {
27909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
27919566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
27929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
27939566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2794e885f1abSBarry Smith     }
2795e885f1abSBarry Smith 
2796df10fb39SFande Kong     if (threshold_print || complete_print) {
2797e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2798e885f1abSBarry Smith       PetscScalar       *cvals;
2799e885f1abSBarry Smith       const PetscInt    *bcols;
2800e885f1abSBarry Smith       const PetscScalar *bvals;
2801e885f1abSBarry Smith 
28029566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28039566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28049566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28059566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28069566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28079566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28080e276705SLisandro Dalcin 
28099566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28109566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2811e885f1abSBarry Smith 
2812e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28139566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28149566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2815e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
281623a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2817e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2818e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2819e885f1abSBarry Smith             cncols += 1;
2820e885f1abSBarry Smith           }
2821e885f1abSBarry Smith         }
282248a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28239566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28249566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2825e885f1abSBarry Smith       }
28269566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28279566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28299566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28309566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2831e885f1abSBarry Smith     }
28329566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
28339566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
28349566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
28352cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
283612837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
283712837594SBarry Smith       jacobian = snes->jacobian_pre;
28389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
28399371c9d4SSatish Balay     } else jacobian = NULL;
284012837594SBarry Smith   }
28419566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
28421baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2843648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
28449566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
28453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2846e885f1abSBarry Smith }
2847e885f1abSBarry Smith 
284862fef451SLois Curfman McInnes /*@
2849f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
285062fef451SLois Curfman McInnes 
2851c3339decSBarry Smith   Collective
2852c7afd0dbSLois Curfman McInnes 
285362fef451SLois Curfman McInnes   Input Parameters:
2854f6dfbefdSBarry Smith + snes - the `SNES` context
2855e4094ef1SJacob Faibussowitsch - X    - input vector
285662fef451SLois Curfman McInnes 
285762fef451SLois Curfman McInnes   Output Parameters:
2858c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2859420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2860fee21e36SBarry Smith 
2861e35cf81dSBarry Smith   Options Database Keys:
286267b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
286367b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2864455a5933SJed 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.
2865455a5933SJed 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
2866693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2867693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2868693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
28694c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
287094d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2871a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2872c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2873dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2874dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2875a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2876a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2877c01495d3SJed Brown 
2878dc4c0fb0SBarry Smith   Level: developer
2879dc4c0fb0SBarry Smith 
2880f6dfbefdSBarry Smith   Note:
288162fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
288262fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
288362fef451SLois Curfman McInnes 
2884420bcc1bSBarry Smith   Developer Note:
2885dc4c0fb0SBarry 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
2886420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2887e885f1abSBarry Smith 
28881cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
288962fef451SLois Curfman McInnes @*/
2890d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2891d71ae5a4SJacob Faibussowitsch {
2892ace3abfcSBarry Smith   PetscBool flag;
28936cab3a1bSJed Brown   DM        dm;
2894942e3340SBarry Smith   DMSNES    sdm;
2895e0e3a89bSBarry Smith   KSP       ksp;
28963a40ed3dSBarry Smith 
28973a40ed3dSBarry Smith   PetscFunctionBegin;
28980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
28990700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2900c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2901e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29029566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29039566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29043232da50SPeter Brune 
290501c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2906fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2907fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2908f5af7f23SKarl Rupp 
29099566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2910fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29119566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29129566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2913ebd3b9afSBarry Smith     if (flag) {
29149566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29159566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2916ebd3b9afSBarry Smith     }
29173ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
291837ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
291963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29209566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2921ebd3b9afSBarry Smith     if (flag) {
29229566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29239566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2924ebd3b9afSBarry Smith     }
29253ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2926e35cf81dSBarry Smith   }
2927efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29289566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29299566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29303ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2931d728fb7dSPeter Brune   }
2932e35cf81dSBarry Smith 
29339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
29349566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2935800f99ffSJeremy L Thompson   {
2936800f99ffSJeremy L Thompson     void           *ctx;
29378434afd1SBarry Smith     SNESJacobianFn *J;
2938800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2939800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2940800f99ffSJeremy L Thompson   }
29419566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
29429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
294328d58a37SPierre Jolivet 
294428d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
29459566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2946a8054027SBarry Smith 
2947e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
29489566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
29493b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
29509566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
29519566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
29523b4f5425SBarry Smith     snes->lagpreconditioner = -1;
29533b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
29549566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
29559566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
295637ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
295763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
29589566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2959d1e9a80fSBarry Smith   } else {
29609566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
29619566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2962a8054027SBarry Smith   }
2963a8054027SBarry Smith 
29644df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
29654df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
29664df93895SStefano Zampini   {
29674df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
29684df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
29694df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
29704df93895SStefano Zampini 
29714df93895SStefano Zampini     snes->vec_sol      = X;
29724df93895SStefano Zampini     snes->jacobian     = A;
29734df93895SStefano Zampini     snes->jacobian_pre = B;
2974494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
29759566063dSJacob Faibussowitsch     PetscCall(SNESTestJacobian(snes));
2976494a190aSStefano Zampini 
29774df93895SStefano Zampini     snes->vec_sol      = xsave;
29784df93895SStefano Zampini     snes->jacobian     = jacobiansave;
29794df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
29804df93895SStefano Zampini   }
29814df93895SStefano Zampini 
2982693365a8SJed Brown   {
2983693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
2984648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
2985648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
2986648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
2987648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2988693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
29890298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2990693365a8SJed Brown       PetscViewer vdraw, vstdout;
29916b3a5b13SJed Brown       PetscBool   flg;
2992693365a8SJed Brown       if (flag_operator) {
29939566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2994693365a8SJed Brown         Bexp = Bexp_mine;
2995693365a8SJed Brown       } else {
2996693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
29979566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
299894ab13aaSBarry Smith         if (flg) Bexp = B;
2999693365a8SJed Brown         else {
3000693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30019566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3002693365a8SJed Brown           Bexp = Bexp_mine;
3003693365a8SJed Brown         }
3004693365a8SJed Brown       }
30059566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30069566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3008693365a8SJed Brown       if (flag_draw || flag_contour) {
30099566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30109566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30110298fd71SBarry Smith       } else vdraw = NULL;
30129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30139566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30149566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30169566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30179566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30189566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30209566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3021693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30229566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30239566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30249566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3025693365a8SJed Brown       }
30269566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30279566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30289566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30299566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3030693365a8SJed Brown     }
3031693365a8SJed Brown   }
30324c30e9fbSJed Brown   {
30336719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
30346719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3035648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3036648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3037648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3038648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3039648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
304027b0f280SBarry Smith     if (flag_threshold) {
30419566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
30429566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
304327b0f280SBarry Smith     }
30446719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
30454c30e9fbSJed Brown       Mat             Bfd;
30464c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3047335efc43SPeter Brune       MatColoring     coloring;
30484c30e9fbSJed Brown       ISColoring      iscoloring;
30494c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
30508434afd1SBarry Smith       SNESFunctionFn *func;
30514c30e9fbSJed Brown       void           *funcctx;
30526719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
30534c30e9fbSJed Brown 
30549566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
30559566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
30569566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
30579566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
30589566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
30599566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
30609566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
30619566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30629566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
30639566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
30644c30e9fbSJed Brown 
30654c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
30669566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
30679566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
30689566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
30699566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
30709566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30719566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
30729566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
30734c30e9fbSJed Brown 
30749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
30754c30e9fbSJed Brown       if (flag_draw || flag_contour) {
30769566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30779566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30780298fd71SBarry Smith       } else vdraw = NULL;
30799566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
30809566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
30819566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
30829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
30839566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30849566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
30859566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
30869566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
30879566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
30889566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
30899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
30909566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30914c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
30929566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30939566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
30949566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
30954c30e9fbSJed Brown       }
30969566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30976719d8e4SJed Brown 
30986719d8e4SJed Brown       if (flag_threshold) {
30996719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31009566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31019566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31026719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31036719d8e4SJed Brown           const PetscScalar *ba, *ca;
31046719d8e4SJed Brown           const PetscInt    *bj, *cj;
31056719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31066719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31079566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31089566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31095f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31106719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31116719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31126719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31136719d8e4SJed Brown               maxentrycol = bj[j];
31146719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31156719d8e4SJed Brown             }
31166719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31176719d8e4SJed Brown               maxdiffcol = bj[j];
31186719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31196719d8e4SJed Brown             }
31206719d8e4SJed Brown             if (rdiff > maxrdiff) {
31216719d8e4SJed Brown               maxrdiffcol = bj[j];
31226719d8e4SJed Brown               maxrdiff    = rdiff;
31236719d8e4SJed Brown             }
31246719d8e4SJed Brown           }
31256719d8e4SJed Brown           if (maxrdiff > 1) {
312663a3b9bcSJacob 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));
31276719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31286719d8e4SJed Brown               PetscReal rdiff;
31296719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
313048a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
31316719d8e4SJed Brown             }
313263a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
31336719d8e4SJed Brown           }
31349566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
31359566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
31366719d8e4SJed Brown         }
31376719d8e4SJed Brown       }
31389566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
31399566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
31404c30e9fbSJed Brown     }
31414c30e9fbSJed Brown   }
31423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31439b94acceSBarry Smith }
31449b94acceSBarry Smith 
31459b94acceSBarry Smith /*@C
31469b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3147044dda88SLois Curfman McInnes   location to store the matrix.
31489b94acceSBarry Smith 
3149c3339decSBarry Smith   Logically Collective
3150c7afd0dbSLois Curfman McInnes 
31519b94acceSBarry Smith   Input Parameters:
3152f6dfbefdSBarry Smith + snes - the `SNES` context
3153e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3154dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
31558434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3156c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3157dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3158dc4c0fb0SBarry Smith 
3159dc4c0fb0SBarry Smith   Level: beginner
31609b94acceSBarry Smith 
31619b94acceSBarry Smith   Notes:
3162dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
316316913363SBarry Smith   each matrix.
316416913363SBarry Smith 
3165dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3166dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3167895c21f2SBarry Smith 
3168dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3169f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3170a8a26c1eSJed Brown 
3171c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3172f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3173c3cc8fd1SJed Brown 
31741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
31758434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
31769b94acceSBarry Smith @*/
31778434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3178d71ae5a4SJacob Faibussowitsch {
31796cab3a1bSJed Brown   DM dm;
31803a7fca6bSBarry Smith 
31813a40ed3dSBarry Smith   PetscFunctionBegin;
31820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3183e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3184e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3185e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3186e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
31879566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31889566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3189e5d3d808SBarry Smith   if (Amat) {
31909566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
31919566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3192f5af7f23SKarl Rupp 
3193e5d3d808SBarry Smith     snes->jacobian = Amat;
31943a7fca6bSBarry Smith   }
3195e5d3d808SBarry Smith   if (Pmat) {
31969566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
31979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3198f5af7f23SKarl Rupp 
3199e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32003a7fca6bSBarry Smith   }
32013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32029b94acceSBarry Smith }
320362fef451SLois Curfman McInnes 
3204c2aafc4cSSatish Balay /*@C
3205b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3206b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3207b4fd4287SBarry Smith 
3208420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3209c7afd0dbSLois Curfman McInnes 
3210b4fd4287SBarry Smith   Input Parameter:
3211b4fd4287SBarry Smith . snes - the nonlinear solver context
3212b4fd4287SBarry Smith 
3213b4fd4287SBarry Smith   Output Parameters:
3214dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3215dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32168434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3217dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3218fee21e36SBarry Smith 
321936851e7fSLois Curfman McInnes   Level: advanced
322036851e7fSLois Curfman McInnes 
32218434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3222b4fd4287SBarry Smith @*/
32238434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3224d71ae5a4SJacob Faibussowitsch {
32256cab3a1bSJed Brown   DM dm;
32266cab3a1bSJed Brown 
32273a40ed3dSBarry Smith   PetscFunctionBegin;
32280700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3229e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3230e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
32319566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3232800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
32333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3234b4fd4287SBarry Smith }
3235b4fd4287SBarry Smith 
3236d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3237d71ae5a4SJacob Faibussowitsch {
323858b371f3SBarry Smith   DM     dm;
323958b371f3SBarry Smith   DMSNES sdm;
324058b371f3SBarry Smith 
324158b371f3SBarry Smith   PetscFunctionBegin;
32429566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32439566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
324458b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
324558b371f3SBarry Smith     DM        dm;
324658b371f3SBarry Smith     PetscBool isdense, ismf;
324758b371f3SBarry Smith 
32489566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32499566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
32509566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
325158b371f3SBarry Smith     if (isdense) {
32529566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
325358b371f3SBarry Smith     } else if (!ismf) {
32549566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
325558b371f3SBarry Smith     }
325658b371f3SBarry Smith   }
32573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
325858b371f3SBarry Smith }
325958b371f3SBarry Smith 
32609b94acceSBarry Smith /*@
32619b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3262272ac6f2SLois Curfman McInnes   of a nonlinear solver.
32639b94acceSBarry Smith 
3264c3339decSBarry Smith   Collective
3265fee21e36SBarry Smith 
32662fe279fdSBarry Smith   Input Parameter:
3267f6dfbefdSBarry Smith . snes - the `SNES` context
3268c7afd0dbSLois Curfman McInnes 
3269dc4c0fb0SBarry Smith   Level: advanced
3270dc4c0fb0SBarry Smith 
3271f6dfbefdSBarry Smith   Note:
3272f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3273f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3274f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3275f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3276f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3277272ac6f2SLois Curfman McInnes 
32781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
32799b94acceSBarry Smith @*/
3280d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3281d71ae5a4SJacob Faibussowitsch {
32826cab3a1bSJed Brown   DM             dm;
3283942e3340SBarry Smith   DMSNES         sdm;
3284c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
32856e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
32869b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
32879b5c1c08SStefano Zampini   Vec            f, fpc;
32889b5c1c08SStefano Zampini   void          *funcctx;
32899b5c1c08SStefano Zampini   void          *jacctx, *appctx;
32909b5c1c08SStefano Zampini   Mat            j, jpre;
32916b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
32926b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
32938434afd1SBarry Smith   SNESFunctionFn *func;
32948434afd1SBarry Smith   SNESJacobianFn *jac;
32953a40ed3dSBarry Smith 
32963a40ed3dSBarry Smith   PetscFunctionBegin;
32970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
32983ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3299fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33009b94acceSBarry Smith 
330148a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
330285385478SLisandro Dalcin 
33039566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
330458c9b817SLisandro Dalcin 
33059566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33069566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33079566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
330858b371f3SBarry Smith 
330948a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3310efd51863SBarry Smith 
331148a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3312b710008aSBarry Smith 
3313d8d34be6SBarry Smith   if (snes->linesearch) {
33149566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33159566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3316d8d34be6SBarry Smith   }
33179e764e56SPeter Brune 
33189b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3319b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3320172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3321172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3322172a4300SPeter Brune   }
3323d8f46077SPeter Brune 
3324efd4aadfSBarry Smith   if (snes->npc) {
33256e2a1849SPeter Brune     /* copy the DM over */
33269566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33279566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33286e2a1849SPeter Brune 
33299566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33309566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
33319566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
33329566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
33339566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
33349566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
33359566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
33369b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
33379566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
33386e2a1849SPeter Brune 
33396e2a1849SPeter Brune     /* copy the function pointers over */
33409566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
33416e2a1849SPeter Brune 
33426e2a1849SPeter Brune     /* default to 1 iteration */
33439566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3344efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
33459566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3346a9936a0cSPeter Brune     } else {
33479566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3348a9936a0cSPeter Brune     }
33499566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
33506e2a1849SPeter Brune 
33516e2a1849SPeter Brune     /* copy the line search context over */
3352d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
33539566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
33549566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
33559566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
33569566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
33579566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
33589566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
33599566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
33606e2a1849SPeter Brune     }
3361d8d34be6SBarry Smith   }
33621baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
33639927e4dfSBarry Smith   if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user));
33646e2a1849SPeter Brune 
336537ec4e1aSPeter Brune   snes->jac_iter = 0;
336637ec4e1aSPeter Brune   snes->pre_iter = 0;
336737ec4e1aSPeter Brune 
3368dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
336958c9b817SLisandro Dalcin 
33709566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
337158b371f3SBarry Smith 
3372b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
33736c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3374d8d34be6SBarry Smith       if (snes->linesearch) {
33759566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
33769566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
33776c67d002SPeter Brune       }
33786c67d002SPeter Brune     }
3379d8d34be6SBarry Smith   }
3380fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
33817aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
33823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33839b94acceSBarry Smith }
33849b94acceSBarry Smith 
338537596af1SLisandro Dalcin /*@
3386f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
338737596af1SLisandro Dalcin 
3388c3339decSBarry Smith   Collective
338937596af1SLisandro Dalcin 
339037596af1SLisandro Dalcin   Input Parameter:
3391f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
339237596af1SLisandro Dalcin 
3393d25893d9SBarry Smith   Level: intermediate
3394d25893d9SBarry Smith 
339595452b02SPatrick Sanan   Notes:
3396f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
339737596af1SLisandro Dalcin 
3398f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3399f6dfbefdSBarry Smith 
34001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
340137596af1SLisandro Dalcin @*/
3402d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3403d71ae5a4SJacob Faibussowitsch {
340437596af1SLisandro Dalcin   PetscFunctionBegin;
340537596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3406d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
34079927e4dfSBarry Smith     PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user));
34080298fd71SBarry Smith     snes->user = NULL;
3409d25893d9SBarry Smith   }
34101baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34118a23116dSBarry Smith 
3412dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34131baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34149e764e56SPeter Brune 
34151baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34169e764e56SPeter Brune 
34179566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34199566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34219566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34229566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34249566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34259566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3426f5af7f23SKarl Rupp 
342740fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
342840fdac6aSLawrence Mitchell 
342937596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
343037596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
34313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
343237596af1SLisandro Dalcin }
343337596af1SLisandro Dalcin 
343452baeb72SSatish Balay /*@
343536d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
343636d43d94SBarry Smith   removes the default viewer.
3437c4421ceaSFande Kong 
3438c3339decSBarry Smith   Collective
3439c4421ceaSFande Kong 
3440c4421ceaSFande Kong   Input Parameter:
3441f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3442c4421ceaSFande Kong 
3443c4421ceaSFande Kong   Level: intermediate
3444c4421ceaSFande Kong 
3445420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3446c4421ceaSFande Kong @*/
3447d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3448d71ae5a4SJacob Faibussowitsch {
3449c4421ceaSFande Kong   PetscInt i;
3450c4421ceaSFande Kong 
3451c4421ceaSFande Kong   PetscFunctionBegin;
3452c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3453c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
345448a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3455c4421ceaSFande Kong   }
3456c4421ceaSFande Kong   snes->numberreasonviews = 0;
3457648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
34583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3459c4421ceaSFande Kong }
3460c4421ceaSFande Kong 
34610764c050SBarry Smith /*@
34629b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3463f6dfbefdSBarry Smith   with `SNESCreate()`.
34649b94acceSBarry Smith 
3465c3339decSBarry Smith   Collective
3466c7afd0dbSLois Curfman McInnes 
34679b94acceSBarry Smith   Input Parameter:
3468f6dfbefdSBarry Smith . snes - the `SNES` context
34699b94acceSBarry Smith 
347036851e7fSLois Curfman McInnes   Level: beginner
347136851e7fSLois Curfman McInnes 
34721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
34739b94acceSBarry Smith @*/
3474d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3475d71ae5a4SJacob Faibussowitsch {
34763a40ed3dSBarry Smith   PetscFunctionBegin;
34773ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3478f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3479f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
34809371c9d4SSatish Balay     *snes = NULL;
34813ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
34829371c9d4SSatish Balay   }
3483d4bb536fSBarry Smith 
3484f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
34859566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
34866b8b9a38SLisandro Dalcin 
3487e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
34889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3489f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
34906d4c513bSLisandro Dalcin 
34919566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
34929566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
34939566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
34949566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
34956b8b9a38SLisandro Dalcin 
34969566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
349748a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
349848a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3499f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3500f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35019566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35039b94acceSBarry Smith }
35049b94acceSBarry Smith 
35059b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35069b94acceSBarry Smith 
3507a8054027SBarry Smith /*@
3508a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3509a8054027SBarry Smith 
3510c3339decSBarry Smith   Logically Collective
3511a8054027SBarry Smith 
3512a8054027SBarry Smith   Input Parameters:
3513f6dfbefdSBarry Smith + snes - the `SNES` context
3514d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35153b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3516a8054027SBarry Smith 
3517a8054027SBarry Smith   Options Database Keys:
3518420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35193d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3520420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35213d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3522a8054027SBarry Smith 
3523dc4c0fb0SBarry Smith   Level: intermediate
3524dc4c0fb0SBarry Smith 
3525420bcc1bSBarry Smith   Notes:
3526a8054027SBarry Smith   The default is 1
3527420bcc1bSBarry Smith 
3528f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3529d8e291bfSBarry Smith 
3530f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3531a8054027SBarry Smith 
3532*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3533f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3534a8054027SBarry Smith @*/
3535d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3536d71ae5a4SJacob Faibussowitsch {
3537a8054027SBarry Smith   PetscFunctionBegin;
35380700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35395f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35405f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3541c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3542a8054027SBarry Smith   snes->lagpreconditioner = lag;
35433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3544a8054027SBarry Smith }
3545a8054027SBarry Smith 
3546efd51863SBarry Smith /*@
3547f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3548efd51863SBarry Smith 
3549c3339decSBarry Smith   Logically Collective
3550efd51863SBarry Smith 
3551efd51863SBarry Smith   Input Parameters:
3552f6dfbefdSBarry Smith + snes  - the `SNES` context
3553efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3554efd51863SBarry Smith 
3555f6dfbefdSBarry Smith   Options Database Key:
355667b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3557efd51863SBarry Smith 
3558efd51863SBarry Smith   Level: intermediate
3559efd51863SBarry Smith 
3560f6dfbefdSBarry Smith   Note:
3561f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3562c0df2a02SJed Brown 
3563*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
3564420bcc1bSBarry Smith           `SNESetDM()`
3565efd51863SBarry Smith @*/
3566d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3567d71ae5a4SJacob Faibussowitsch {
3568efd51863SBarry Smith   PetscFunctionBegin;
3569efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3570efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3571efd51863SBarry Smith   snes->gridsequence = steps;
35723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3573efd51863SBarry Smith }
3574efd51863SBarry Smith 
3575fa19ca70SBarry Smith /*@
3576f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3577fa19ca70SBarry Smith 
3578c3339decSBarry Smith   Logically Collective
3579fa19ca70SBarry Smith 
3580fa19ca70SBarry Smith   Input Parameter:
3581f6dfbefdSBarry Smith . snes - the `SNES` context
3582fa19ca70SBarry Smith 
3583fa19ca70SBarry Smith   Output Parameter:
3584fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3585fa19ca70SBarry Smith 
3586fa19ca70SBarry Smith   Level: intermediate
3587fa19ca70SBarry Smith 
3588*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3589fa19ca70SBarry Smith @*/
3590d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3591d71ae5a4SJacob Faibussowitsch {
3592fa19ca70SBarry Smith   PetscFunctionBegin;
3593fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3594fa19ca70SBarry Smith   *steps = snes->gridsequence;
35953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3596fa19ca70SBarry Smith }
3597fa19ca70SBarry Smith 
3598a8054027SBarry Smith /*@
3599f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3600a8054027SBarry Smith 
36013f9fe445SBarry Smith   Not Collective
3602a8054027SBarry Smith 
3603a8054027SBarry Smith   Input Parameter:
3604f6dfbefdSBarry Smith . snes - the `SNES` context
3605a8054027SBarry Smith 
3606a8054027SBarry Smith   Output Parameter:
3607a8054027SBarry 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
36083b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3609a8054027SBarry Smith 
3610dc4c0fb0SBarry Smith   Level: intermediate
3611dc4c0fb0SBarry Smith 
3612a8054027SBarry Smith   Notes:
3613a8054027SBarry Smith   The default is 1
3614f6dfbefdSBarry Smith 
3615a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3616a8054027SBarry Smith 
3617*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3618a8054027SBarry Smith @*/
3619d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3620d71ae5a4SJacob Faibussowitsch {
3621a8054027SBarry Smith   PetscFunctionBegin;
36220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3623a8054027SBarry Smith   *lag = snes->lagpreconditioner;
36243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3625a8054027SBarry Smith }
3626a8054027SBarry Smith 
3627e35cf81dSBarry Smith /*@
3628f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3629e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3630e35cf81dSBarry Smith 
3631c3339decSBarry Smith   Logically Collective
3632e35cf81dSBarry Smith 
3633e35cf81dSBarry Smith   Input Parameters:
3634f6dfbefdSBarry Smith + snes - the `SNES` context
3635e35cf81dSBarry 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
3636fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3637e35cf81dSBarry Smith 
3638e35cf81dSBarry Smith   Options Database Keys:
363979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36403d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
364179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36423d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3643e35cf81dSBarry Smith 
3644dc4c0fb0SBarry Smith   Level: intermediate
3645dc4c0fb0SBarry Smith 
3646e35cf81dSBarry Smith   Notes:
3647e35cf81dSBarry Smith   The default is 1
3648f6dfbefdSBarry Smith 
3649e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3650f6dfbefdSBarry Smith 
3651fe3ffe1eSBarry 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
3652fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3653e35cf81dSBarry Smith 
3654*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3655e35cf81dSBarry Smith @*/
3656d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3657d71ae5a4SJacob Faibussowitsch {
3658e35cf81dSBarry Smith   PetscFunctionBegin;
36590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36605f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36615f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3662c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3663e35cf81dSBarry Smith   snes->lagjacobian = lag;
36643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3665e35cf81dSBarry Smith }
3666e35cf81dSBarry Smith 
3667e35cf81dSBarry Smith /*@
3668f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3669e35cf81dSBarry Smith 
36703f9fe445SBarry Smith   Not Collective
3671e35cf81dSBarry Smith 
3672e35cf81dSBarry Smith   Input Parameter:
3673f6dfbefdSBarry Smith . snes - the `SNES` context
3674e35cf81dSBarry Smith 
3675e35cf81dSBarry Smith   Output Parameter:
3676e35cf81dSBarry 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
3677e35cf81dSBarry Smith          the Jacobian is built etc.
3678e35cf81dSBarry Smith 
3679dc4c0fb0SBarry Smith   Level: intermediate
3680dc4c0fb0SBarry Smith 
3681e35cf81dSBarry Smith   Notes:
3682e35cf81dSBarry Smith   The default is 1
3683f6dfbefdSBarry Smith 
3684f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3685e35cf81dSBarry Smith 
3686*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3687e35cf81dSBarry Smith 
3688e35cf81dSBarry Smith @*/
3689d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3690d71ae5a4SJacob Faibussowitsch {
3691e35cf81dSBarry Smith   PetscFunctionBegin;
36920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3693e35cf81dSBarry Smith   *lag = snes->lagjacobian;
36943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3695e35cf81dSBarry Smith }
3696e35cf81dSBarry Smith 
369737ec4e1aSPeter Brune /*@
3698f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
369937ec4e1aSPeter Brune 
3700c3339decSBarry Smith   Logically collective
370137ec4e1aSPeter Brune 
3702d8d19677SJose E. Roman   Input Parameters:
3703f6dfbefdSBarry Smith + snes - the `SNES` context
37049d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
370537ec4e1aSPeter Brune 
370637ec4e1aSPeter Brune   Options Database Keys:
370779a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37083d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
370979a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37103d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37113d5a8a6aSBarry Smith 
3712dc4c0fb0SBarry Smith   Level: advanced
3713dc4c0fb0SBarry Smith 
371495452b02SPatrick Sanan   Notes:
3715420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3716f6dfbefdSBarry Smith 
371795452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
371837ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
371937ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
372037ec4e1aSPeter Brune 
372142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
372237ec4e1aSPeter Brune @*/
3723d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3724d71ae5a4SJacob Faibussowitsch {
372537ec4e1aSPeter Brune   PetscFunctionBegin;
372637ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
372737ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
372837ec4e1aSPeter Brune   snes->lagjac_persist = flg;
37293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
373037ec4e1aSPeter Brune }
373137ec4e1aSPeter Brune 
373237ec4e1aSPeter Brune /*@
3733d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
373437ec4e1aSPeter Brune 
3735c3339decSBarry Smith   Logically Collective
373637ec4e1aSPeter Brune 
3737d8d19677SJose E. Roman   Input Parameters:
3738f6dfbefdSBarry Smith + snes - the `SNES` context
37399d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
374037ec4e1aSPeter Brune 
374137ec4e1aSPeter Brune   Options Database Keys:
374279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37433d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
374479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37453d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
374637ec4e1aSPeter Brune 
3747dc4c0fb0SBarry Smith   Level: developer
3748dc4c0fb0SBarry Smith 
374995452b02SPatrick Sanan   Notes:
3750420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3751f6dfbefdSBarry Smith 
375295452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
375337ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
375437ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
375537ec4e1aSPeter Brune 
37561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
375737ec4e1aSPeter Brune @*/
3758d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3759d71ae5a4SJacob Faibussowitsch {
376037ec4e1aSPeter Brune   PetscFunctionBegin;
376137ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
376237ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
376337ec4e1aSPeter Brune   snes->lagpre_persist = flg;
37643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
376537ec4e1aSPeter Brune }
376637ec4e1aSPeter Brune 
37679b94acceSBarry Smith /*@
3768f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3769be5caee7SBarry Smith 
3770c3339decSBarry Smith   Logically Collective
3771be5caee7SBarry Smith 
3772be5caee7SBarry Smith   Input Parameters:
3773f6dfbefdSBarry Smith + snes  - the `SNES` context
3774f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3775be5caee7SBarry Smith 
3776f6dfbefdSBarry Smith   Options Database Key:
3777be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3778be5caee7SBarry Smith 
3779dc4c0fb0SBarry Smith   Level: intermediate
3780dc4c0fb0SBarry Smith 
3781f6dfbefdSBarry Smith   Note:
3782f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3783be5caee7SBarry Smith 
3784*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3785be5caee7SBarry Smith @*/
3786d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3787d71ae5a4SJacob Faibussowitsch {
3788be5caee7SBarry Smith   PetscFunctionBegin;
3789be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3790be5caee7SBarry Smith   snes->forceiteration = force;
37913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3792be5caee7SBarry Smith }
3793be5caee7SBarry Smith 
379485216dc7SFande Kong /*@
3795f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
379685216dc7SFande Kong 
3797c3339decSBarry Smith   Logically Collective
379885216dc7SFande Kong 
37992fe279fdSBarry Smith   Input Parameter:
3800f6dfbefdSBarry Smith . snes - the `SNES` context
380185216dc7SFande Kong 
380285216dc7SFande Kong   Output Parameter:
3803dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
380485216dc7SFande Kong 
380506dd6b0eSSatish Balay   Level: intermediate
380606dd6b0eSSatish Balay 
3807*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
380885216dc7SFande Kong @*/
3809d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3810d71ae5a4SJacob Faibussowitsch {
381185216dc7SFande Kong   PetscFunctionBegin;
381285216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
381385216dc7SFande Kong   *force = snes->forceiteration;
38143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
381585216dc7SFande Kong }
3816be5caee7SBarry Smith 
3817be5caee7SBarry Smith /*@
3818f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
38199b94acceSBarry Smith 
3820c3339decSBarry Smith   Logically Collective
3821c7afd0dbSLois Curfman McInnes 
38229b94acceSBarry Smith   Input Parameters:
3823f6dfbefdSBarry Smith + snes   - the `SNES` context
382470441072SBarry Smith . abstol - absolute convergence tolerance
382533174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
38265358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3827f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
382877e5a1f9SBarry Smith - maxf   - maximum number of function evaluations (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3829fee21e36SBarry Smith 
383033174efeSLois Curfman McInnes   Options Database Keys:
383177e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
383277e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
383377e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
383477e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
383577e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
38369b94acceSBarry Smith 
383736851e7fSLois Curfman McInnes   Level: intermediate
383836851e7fSLois Curfman McInnes 
383977e5a1f9SBarry Smith   Note:
384077e5a1f9SBarry Smith   All parameters must be non-negative
384177e5a1f9SBarry Smith 
384277e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
384377e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
384477e5a1f9SBarry Smith 
384577e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
384677e5a1f9SBarry Smith 
384777e5a1f9SBarry Smith   Fortran Note:
384877e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
384977e5a1f9SBarry Smith 
3850*3201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
38519b94acceSBarry Smith @*/
3852d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3853d71ae5a4SJacob Faibussowitsch {
38543a40ed3dSBarry Smith   PetscFunctionBegin;
38550700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3856c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3857c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3858c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3859c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3860c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3861c5eb9154SBarry Smith 
386277e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
386377e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
386477e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
38655f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3866ab54825eSJed Brown     snes->abstol = abstol;
3867ab54825eSJed Brown   }
386877e5a1f9SBarry Smith 
386977e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
387077e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
387177e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
38725f80ce2aSJacob 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);
3873ab54825eSJed Brown     snes->rtol = rtol;
3874ab54825eSJed Brown   }
387577e5a1f9SBarry Smith 
387677e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
387777e5a1f9SBarry Smith     snes->stol = snes->default_stol;
387877e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
38795f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3880c60f73f4SPeter Brune     snes->stol = stol;
3881ab54825eSJed Brown   }
388277e5a1f9SBarry Smith 
388377e5a1f9SBarry Smith   if (maxit == (PetscInt)PETSC_DETERMINE) {
388477e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
388577e5a1f9SBarry Smith   } else if (maxit == (PetscInt)PETSC_UNLIMITED) {
388677e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
388777e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
388863a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3889ab54825eSJed Brown     snes->max_its = maxit;
3890ab54825eSJed Brown   }
389177e5a1f9SBarry Smith 
389277e5a1f9SBarry Smith   if (maxf == (PetscInt)PETSC_DETERMINE) {
389377e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
389477e5a1f9SBarry Smith   } else if (maxf == (PetscInt)PETSC_UNLIMITED || maxf == -1) {
389577e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
389677e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
389777e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3898ab54825eSJed Brown     snes->max_funcs = maxf;
3899ab54825eSJed Brown   }
39003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39019b94acceSBarry Smith }
39029b94acceSBarry Smith 
3903e4d06f11SPatrick Farrell /*@
3904f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3905e4d06f11SPatrick Farrell 
3906c3339decSBarry Smith   Logically Collective
3907e4d06f11SPatrick Farrell 
3908e4d06f11SPatrick Farrell   Input Parameters:
3909f6dfbefdSBarry Smith + snes   - the `SNES` context
3910*3201ab8dSStefano Zampini - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test.
3911e4d06f11SPatrick Farrell 
3912f6dfbefdSBarry Smith   Options Database Key:
3913dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3914e4d06f11SPatrick Farrell 
3915e4d06f11SPatrick Farrell   Level: intermediate
3916e4d06f11SPatrick Farrell 
391777e5a1f9SBarry Smith   Notes:
391877e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
3919e5cd489fSStefano Zampini 
392077e5a1f9SBarry Smith   Fortran Note:
392177e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
392277e5a1f9SBarry Smith 
392377e5a1f9SBarry Smith   Developer Note:
392477e5a1f9SBarry Smith   Also supports the deprecated -1 to indicate no bound on the growth of the residual
392577e5a1f9SBarry Smith 
392677e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
3927e4d06f11SPatrick Farrell @*/
3928d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3929d71ae5a4SJacob Faibussowitsch {
3930e4d06f11SPatrick Farrell   PetscFunctionBegin;
3931e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3932e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
393377e5a1f9SBarry Smith 
393477e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
393577e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
393677e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
393777e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
393877e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
393977e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
394077e5a1f9SBarry Smith     snes->divtol = divtol;
394177e5a1f9SBarry Smith   }
39423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3943e4d06f11SPatrick Farrell }
3944e4d06f11SPatrick Farrell 
39459b94acceSBarry Smith /*@
394633174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
394733174efeSLois Curfman McInnes 
3948c7afd0dbSLois Curfman McInnes   Not Collective
3949c7afd0dbSLois Curfman McInnes 
395077e5a1f9SBarry Smith   Input Parameter:
395177e5a1f9SBarry Smith . snes - the `SNES` context
395277e5a1f9SBarry Smith 
395377e5a1f9SBarry Smith   Output Parameters:
395477e5a1f9SBarry Smith + atol  - absolute convergence tolerance
395533174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
395677e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
395733174efeSLois Curfman McInnes . maxit - maximum number of iterations
395877e5a1f9SBarry Smith - maxf  - maximum number of function evaluations, `PETSC_UNLIMITED` indicates no bound
3959fee21e36SBarry Smith 
396036851e7fSLois Curfman McInnes   Level: intermediate
396136851e7fSLois Curfman McInnes 
3962dc4c0fb0SBarry Smith   Note:
3963dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3964dc4c0fb0SBarry Smith 
39651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
396633174efeSLois Curfman McInnes @*/
3967d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3968d71ae5a4SJacob Faibussowitsch {
39693a40ed3dSBarry Smith   PetscFunctionBegin;
39700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
397185385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
397233174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3973c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
397433174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
397533174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
39763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
397733174efeSLois Curfman McInnes }
397833174efeSLois Curfman McInnes 
3979e4d06f11SPatrick Farrell /*@
3980e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3981e4d06f11SPatrick Farrell 
3982e4d06f11SPatrick Farrell   Not Collective
3983e4d06f11SPatrick Farrell 
3984e4d06f11SPatrick Farrell   Input Parameters:
3985f6dfbefdSBarry Smith + snes   - the `SNES` context
3986e4d06f11SPatrick Farrell - divtol - divergence tolerance
3987e4d06f11SPatrick Farrell 
3988e4d06f11SPatrick Farrell   Level: intermediate
3989e4d06f11SPatrick Farrell 
39901cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3991e4d06f11SPatrick Farrell @*/
3992d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3993d71ae5a4SJacob Faibussowitsch {
3994e4d06f11SPatrick Farrell   PetscFunctionBegin;
3995e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3996e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
39973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3998e4d06f11SPatrick Farrell }
3999e4d06f11SPatrick Farrell 
40006ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40016ba87a44SLisandro Dalcin 
4002d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4003d71ae5a4SJacob Faibussowitsch {
4004b271bb04SBarry Smith   PetscDrawLG      lg;
4005b271bb04SBarry Smith   PetscReal        x, y, per;
4006b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4007b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4008b271bb04SBarry Smith   PetscDraw        draw;
4009b271bb04SBarry Smith 
4010459f5d12SBarry Smith   PetscFunctionBegin;
40114d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40129566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40139566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40149566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40159566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4016b271bb04SBarry Smith   x = (PetscReal)n;
401777b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
401894c9c6d3SKarl Rupp   else y = -15.0;
40199566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40206934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40219566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40229566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4023b271bb04SBarry Smith   }
4024b271bb04SBarry Smith 
40259566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
40269566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40279566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4028aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
40299566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4030b271bb04SBarry Smith   x = (PetscReal)n;
4031b271bb04SBarry Smith   y = 100.0 * per;
40329566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40336934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40349566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40359566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4036b271bb04SBarry Smith   }
4037b271bb04SBarry Smith 
40389566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
40399371c9d4SSatish Balay   if (!n) {
40409371c9d4SSatish Balay     prev = rnorm;
40419371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
40429371c9d4SSatish Balay   }
40439566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40449566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4045b271bb04SBarry Smith   x = (PetscReal)n;
4046b271bb04SBarry Smith   y = (prev - rnorm) / prev;
40479566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40486934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40499566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40509566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4051b271bb04SBarry Smith   }
4052b271bb04SBarry Smith 
40539566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
40549566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40559566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40569566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4057b271bb04SBarry Smith   x = (PetscReal)n;
4058b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4059b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
40609566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4061b271bb04SBarry Smith   }
40626934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40639566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40649566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4065b271bb04SBarry Smith   }
4066b271bb04SBarry Smith   prev = rnorm;
40673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4068b271bb04SBarry Smith }
4069b271bb04SBarry Smith 
4070228d79bcSJed Brown /*@
40712d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
40722d157150SStefano Zampini 
40732d157150SStefano Zampini   Collective
40742d157150SStefano Zampini 
40752d157150SStefano Zampini   Input Parameters:
40762d157150SStefano Zampini + snes  - the `SNES` context
40772d157150SStefano Zampini . it    - current iteration
40782d157150SStefano Zampini . xnorm - 2-norm of current iterate
40792d157150SStefano Zampini . snorm - 2-norm of current step
40802d157150SStefano Zampini - fnorm - 2-norm of function
40812d157150SStefano Zampini 
40822d157150SStefano Zampini   Level: developer
40832d157150SStefano Zampini 
40842d157150SStefano Zampini   Note:
4085420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
40862d157150SStefano Zampini   It does not typically need to be called by the user.
40872d157150SStefano Zampini 
4088be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
40892d157150SStefano Zampini @*/
40902d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
40912d157150SStefano Zampini {
40922d157150SStefano Zampini   PetscFunctionBegin;
40932d157150SStefano Zampini   if (!snes->reason) {
40942d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
40952d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
40962d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
40972d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
40982d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
40992d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41002d157150SStefano Zampini     }
41012d157150SStefano Zampini   }
41022d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41032d157150SStefano Zampini }
41042d157150SStefano Zampini 
41052d157150SStefano Zampini /*@
4106228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
4107228d79bcSJed Brown 
4108c3339decSBarry Smith   Collective
4109228d79bcSJed Brown 
4110228d79bcSJed Brown   Input Parameters:
4111f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
4112228d79bcSJed Brown . iter  - iteration number
4113228d79bcSJed Brown - rnorm - relative norm of the residual
4114228d79bcSJed Brown 
4115dc4c0fb0SBarry Smith   Level: developer
4116dc4c0fb0SBarry Smith 
4117f6dfbefdSBarry Smith   Note:
4118420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4119228d79bcSJed Brown   It does not typically need to be called by the user.
4120228d79bcSJed Brown 
41211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4122228d79bcSJed Brown @*/
4123d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4124d71ae5a4SJacob Faibussowitsch {
41257a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
41267a03ce2fSLisandro Dalcin 
41277a03ce2fSLisandro Dalcin   PetscFunctionBegin;
41285f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
41299566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
413048a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
41319566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
41323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41337a03ce2fSLisandro Dalcin }
41347a03ce2fSLisandro Dalcin 
41359b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
41369b94acceSBarry Smith 
4137bf388a1fSBarry Smith /*MC
4138f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4139bf388a1fSBarry Smith 
4140bf388a1fSBarry Smith      Synopsis:
4141aaa7dc30SBarry Smith      #include <petscsnes.h>
414237fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4143bf388a1fSBarry Smith 
4144c3339decSBarry Smith      Collective
41451843f636SBarry Smith 
41461843f636SBarry Smith     Input Parameters:
4147f6dfbefdSBarry Smith +    snes - the `SNES` context
4148bf388a1fSBarry Smith .    its - iteration number
4149bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4150bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4151bf388a1fSBarry Smith 
4152878cb397SSatish Balay    Level: advanced
4153878cb397SSatish Balay 
41541cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4155bf388a1fSBarry Smith M*/
4156bf388a1fSBarry Smith 
41579b94acceSBarry Smith /*@C
4158a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
41599b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
41609b94acceSBarry Smith   progress.
41619b94acceSBarry Smith 
4162c3339decSBarry Smith   Logically Collective
4163fee21e36SBarry Smith 
4164c7afd0dbSLois Curfman McInnes   Input Parameters:
4165f6dfbefdSBarry Smith + snes           - the `SNES` context
416620f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4167420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4168dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
41699b94acceSBarry Smith 
41709665c990SLois Curfman McInnes   Options Database Keys:
4171f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4172798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4173dc4c0fb0SBarry 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
4174c7afd0dbSLois Curfman McInnes                                 the options database.
41759665c990SLois Curfman McInnes 
4176dc4c0fb0SBarry Smith   Level: intermediate
4177dc4c0fb0SBarry Smith 
4178f6dfbefdSBarry Smith   Note:
41796bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4180f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
41816bc08f3fSLois Curfman McInnes   order in which they were set.
4182639f9d9dSBarry Smith 
4183420bcc1bSBarry Smith   Fortran Note:
4184f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4185025f1a04SBarry Smith 
41861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
41879b94acceSBarry Smith @*/
4188d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4189d71ae5a4SJacob Faibussowitsch {
4190b90d0a6eSBarry Smith   PetscInt  i;
419178064530SBarry Smith   PetscBool identical;
4192b90d0a6eSBarry Smith 
41933a40ed3dSBarry Smith   PetscFunctionBegin;
41940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4195b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
41969566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
41973ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4198649052a6SBarry Smith   }
41995f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42006e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4201b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4202639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
42033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42049b94acceSBarry Smith }
42059b94acceSBarry Smith 
4206a278d85bSSatish Balay /*@
4207f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42085cd90555SBarry Smith 
4209c3339decSBarry Smith   Logically Collective
4210c7afd0dbSLois Curfman McInnes 
42112fe279fdSBarry Smith   Input Parameter:
4212f6dfbefdSBarry Smith . snes - the `SNES` context
42135cd90555SBarry Smith 
42141a480d89SAdministrator   Options Database Key:
4215a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4216dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4217c7afd0dbSLois Curfman McInnes     set via the options database
42185cd90555SBarry Smith 
4219dc4c0fb0SBarry Smith   Level: intermediate
4220dc4c0fb0SBarry Smith 
4221f6dfbefdSBarry Smith   Note:
4222f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
42235cd90555SBarry Smith 
42241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
42255cd90555SBarry Smith @*/
4226d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4227d71ae5a4SJacob Faibussowitsch {
4228d952e501SBarry Smith   PetscInt i;
4229d952e501SBarry Smith 
42305cd90555SBarry Smith   PetscFunctionBegin;
42310700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4232d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
423348a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4234d952e501SBarry Smith   }
42355cd90555SBarry Smith   snes->numbermonitors = 0;
42363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42375cd90555SBarry Smith }
42385cd90555SBarry Smith 
4239bf388a1fSBarry Smith /*MC
4240bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4241bf388a1fSBarry Smith 
4242bf388a1fSBarry Smith      Synopsis:
4243aaa7dc30SBarry Smith      #include <petscsnes.h>
424437fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4245bf388a1fSBarry Smith 
4246c3339decSBarry Smith      Collective
42471843f636SBarry Smith 
42481843f636SBarry Smith     Input Parameters:
4249f6dfbefdSBarry Smith +    snes - the `SNES` context
4250bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4251bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4252bf388a1fSBarry Smith .    gnorm - 2-norm of current step
42531843f636SBarry Smith .    f - 2-norm of function
42541843f636SBarry Smith -    cctx - [optional] convergence context
42551843f636SBarry Smith 
42561843f636SBarry Smith     Output Parameter:
42571843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4258bf388a1fSBarry Smith 
4259878cb397SSatish Balay    Level: intermediate
4260bf388a1fSBarry Smith 
42611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4262bf388a1fSBarry Smith M*/
4263bf388a1fSBarry Smith 
42649b94acceSBarry Smith /*@C
42659b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
42669b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
42679b94acceSBarry Smith 
4268c3339decSBarry Smith   Logically Collective
4269fee21e36SBarry Smith 
4270c7afd0dbSLois Curfman McInnes   Input Parameters:
4271f6dfbefdSBarry Smith + snes                        - the `SNES` context
4272e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4273dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4274dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
42759b94acceSBarry Smith 
427636851e7fSLois Curfman McInnes   Level: advanced
427736851e7fSLois Curfman McInnes 
42781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
42799b94acceSBarry Smith @*/
4280d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4281d71ae5a4SJacob Faibussowitsch {
42823a40ed3dSBarry Smith   PetscFunctionBegin;
42830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4284e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
42851baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4286bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
42877f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
428885385478SLisandro Dalcin   snes->cnvP                  = cctx;
42893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42909b94acceSBarry Smith }
42919b94acceSBarry Smith 
429252baeb72SSatish Balay /*@
4293f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4294184914b5SBarry Smith 
4295184914b5SBarry Smith   Not Collective
4296184914b5SBarry Smith 
4297184914b5SBarry Smith   Input Parameter:
4298f6dfbefdSBarry Smith . snes - the `SNES` context
4299184914b5SBarry Smith 
4300184914b5SBarry Smith   Output Parameter:
4301f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4302184914b5SBarry Smith 
4303f6dfbefdSBarry Smith   Options Database Key:
43046a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43056a4d7782SBarry Smith 
4306184914b5SBarry Smith   Level: intermediate
4307184914b5SBarry Smith 
4308f6dfbefdSBarry Smith   Note:
4309f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4310184914b5SBarry Smith 
43111cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4312184914b5SBarry Smith @*/
4313d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4314d71ae5a4SJacob Faibussowitsch {
4315184914b5SBarry Smith   PetscFunctionBegin;
43160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43174f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4318184914b5SBarry Smith   *reason = snes->reason;
43193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4320184914b5SBarry Smith }
4321184914b5SBarry Smith 
4322c4421ceaSFande Kong /*@C
4323f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4324c4421ceaSFande Kong 
4325c4421ceaSFande Kong   Not Collective
4326c4421ceaSFande Kong 
4327c4421ceaSFande Kong   Input Parameter:
4328f6dfbefdSBarry Smith . snes - the `SNES` context
4329c4421ceaSFande Kong 
4330c4421ceaSFande Kong   Output Parameter:
4331dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4332c4421ceaSFande Kong 
433399c90e12SSatish Balay   Level: beginner
4334c4421ceaSFande Kong 
43351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4336c4421ceaSFande Kong @*/
4337d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4338d71ae5a4SJacob Faibussowitsch {
4339c4421ceaSFande Kong   PetscFunctionBegin;
4340c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43414f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4342c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
43433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4344c4421ceaSFande Kong }
4345c4421ceaSFande Kong 
434633866048SMatthew G. Knepley /*@
4347f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
434833866048SMatthew G. Knepley 
434933866048SMatthew G. Knepley   Not Collective
435033866048SMatthew G. Knepley 
435133866048SMatthew G. Knepley   Input Parameters:
4352f6dfbefdSBarry Smith + snes   - the `SNES` context
4353f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
435433866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
435533866048SMatthew G. Knepley 
4356f6dfbefdSBarry Smith   Level: developer
4357f6dfbefdSBarry Smith 
4358420bcc1bSBarry Smith   Developer Note:
4359f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
436033866048SMatthew G. Knepley 
43611cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
436233866048SMatthew G. Knepley @*/
4363d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4364d71ae5a4SJacob Faibussowitsch {
436533866048SMatthew G. Knepley   PetscFunctionBegin;
436633866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43675f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
436833866048SMatthew G. Knepley   snes->reason = reason;
43693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
437033866048SMatthew G. Knepley }
437133866048SMatthew G. Knepley 
4372c9005455SLois Curfman McInnes /*@
4373420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4374c9005455SLois Curfman McInnes 
4375c3339decSBarry Smith   Logically Collective
4376fee21e36SBarry Smith 
4377c7afd0dbSLois Curfman McInnes   Input Parameters:
4378f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
43798c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4380cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4381420bcc1bSBarry Smith . na    - size of `a` and `its`
4382f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4383758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4384c7afd0dbSLois Curfman McInnes 
4385dc4c0fb0SBarry Smith   Level: intermediate
4386dc4c0fb0SBarry Smith 
4387308dcc3eSBarry Smith   Notes:
438877e5a1f9SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` then a
438977e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4390308dcc3eSBarry Smith 
4391c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4392c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4393c9005455SLois Curfman McInnes   during the section of code that is being timed.
4394c9005455SLois Curfman McInnes 
4395420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4396420bcc1bSBarry Smith 
43971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4398c9005455SLois Curfman McInnes @*/
4399d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4400d71ae5a4SJacob Faibussowitsch {
44013a40ed3dSBarry Smith   PetscFunctionBegin;
44020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44034f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44044f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44057a1ec6d4SBarry Smith   if (!a) {
440677e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44079566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4408071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4409308dcc3eSBarry Smith   }
4410c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4411758f92a0SBarry Smith   snes->conv_hist_its   = its;
4412115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4413a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4414758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4416758f92a0SBarry Smith }
4417758f92a0SBarry Smith 
4418d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4419c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4420c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
442199e0435eSBarry Smith 
4422d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4423d71ae5a4SJacob Faibussowitsch {
4424308dcc3eSBarry Smith   mxArray   *mat;
4425308dcc3eSBarry Smith   PetscInt   i;
4426308dcc3eSBarry Smith   PetscReal *ar;
4427308dcc3eSBarry Smith 
4428308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4429308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4430f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
443111cc89d2SBarry Smith   return mat;
4432308dcc3eSBarry Smith }
4433308dcc3eSBarry Smith #endif
4434308dcc3eSBarry Smith 
44350c4c9dddSBarry Smith /*@C
4436420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4437758f92a0SBarry Smith 
44383f9fe445SBarry Smith   Not Collective
4439758f92a0SBarry Smith 
4440758f92a0SBarry Smith   Input Parameter:
4441f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4442758f92a0SBarry Smith 
4443758f92a0SBarry Smith   Output Parameters:
4444f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4445758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4446758f92a0SBarry Smith          negative if not converged) for each solve.
444720f4b53cSBarry Smith - na  - size of `a` and `its`
4448758f92a0SBarry Smith 
4449dc4c0fb0SBarry Smith   Level: intermediate
4450dc4c0fb0SBarry Smith 
445120f4b53cSBarry Smith   Note:
445220f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
445320f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
445420f4b53cSBarry Smith   during the section of code that is being timed.
445520f4b53cSBarry Smith 
4456420bcc1bSBarry Smith   Fortran Note:
4457758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4458dc4c0fb0SBarry Smith .vb
4459dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4460dc4c0fb0SBarry Smith .ve
4461758f92a0SBarry Smith 
44621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4463758f92a0SBarry Smith @*/
4464d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4465d71ae5a4SJacob Faibussowitsch {
4466758f92a0SBarry Smith   PetscFunctionBegin;
44670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4468758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4469758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4470115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
44713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4472c9005455SLois Curfman McInnes }
4473c9005455SLois Curfman McInnes 
4474ac226902SBarry Smith /*@C
447576b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4476eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
447753e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
447853e5d35bSStefano Zampini   evaluation.
447976b2cf59SMatthew Knepley 
4480c3339decSBarry Smith   Logically Collective
448176b2cf59SMatthew Knepley 
448276b2cf59SMatthew Knepley   Input Parameters:
4483a2b725a8SWilliam Gropp + snes - The nonlinear solver context
448453e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
448576b2cf59SMatthew Knepley 
4486fe97e370SBarry Smith   Level: advanced
4487fe97e370SBarry Smith 
4488420bcc1bSBarry Smith   Notes:
4489f6dfbefdSBarry 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
4490f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
449153e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
449253e5d35bSStefano Zampini   right before the direction step is computed.
449353e5d35bSStefano Zampini   Users are free to modify the current residual vector,
449453e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
449553e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
449653e5d35bSStefano Zampini   vectors.
449776b2cf59SMatthew Knepley 
4498aaa8cc7dSPierre 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.
44996b7fb656SBarry Smith 
4500e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
450153e5d35bSStefano Zampini          `SNESMonitorSet()`
450276b2cf59SMatthew Knepley @*/
450353e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4504d71ae5a4SJacob Faibussowitsch {
450576b2cf59SMatthew Knepley   PetscFunctionBegin;
45060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4507e7788613SBarry Smith   snes->ops->update = func;
45083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
450976b2cf59SMatthew Knepley }
451076b2cf59SMatthew Knepley 
4511ffeef943SBarry Smith /*@
4512f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
45132a359c20SBarry Smith 
4514c3339decSBarry Smith   Collective
45152a359c20SBarry Smith 
4516e4094ef1SJacob Faibussowitsch   Input Parameters:
4517f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
45182a359c20SBarry Smith - viewer - the viewer to display the reason
45192a359c20SBarry Smith 
45202a359c20SBarry Smith   Options Database Keys:
4521ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4522ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4523eafd5ff0SAlex Lindsay 
4524420bcc1bSBarry Smith   Level: beginner
4525420bcc1bSBarry Smith 
4526f6dfbefdSBarry Smith   Note:
4527f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4528f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
45292a359c20SBarry Smith 
45301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4531f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4532f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4533db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
45342a359c20SBarry Smith @*/
4535d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4536d71ae5a4SJacob Faibussowitsch {
453775cca76cSMatthew G. Knepley   PetscViewerFormat format;
45382a359c20SBarry Smith   PetscBool         isAscii;
45392a359c20SBarry Smith 
45402a359c20SBarry Smith   PetscFunctionBegin;
454119a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
45429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
45432a359c20SBarry Smith   if (isAscii) {
45449566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
454565bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
454675cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
454775cca76cSMatthew G. Knepley       DM       dm;
454875cca76cSMatthew G. Knepley       Vec      u;
454975cca76cSMatthew G. Knepley       PetscDS  prob;
455075cca76cSMatthew G. Knepley       PetscInt Nf, f;
455195cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
455295cbbfd3SMatthew G. Knepley       void    **exactCtx;
455375cca76cSMatthew G. Knepley       PetscReal error;
455475cca76cSMatthew G. Knepley 
45559566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
45569566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
45579566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
45589566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
45599566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
45609566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
45619566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
45629566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
45639566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
456463a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
456575cca76cSMatthew G. Knepley     }
4566eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
45672a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
456863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
45692a359c20SBarry Smith       } else {
457063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
45712a359c20SBarry Smith       }
4572eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
45732a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
457463a3b9bcSJacob 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));
45752a359c20SBarry Smith       } else {
457663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
45772a359c20SBarry Smith       }
45782a359c20SBarry Smith     }
457965bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
45802a359c20SBarry Smith   }
45813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45822a359c20SBarry Smith }
45832a359c20SBarry Smith 
4584c4421ceaSFande Kong /*@C
4585c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4586aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4587c4421ceaSFande Kong 
4588c3339decSBarry Smith   Logically Collective
4589c4421ceaSFande Kong 
4590c4421ceaSFande Kong   Input Parameters:
4591f6dfbefdSBarry Smith + snes              - the `SNES` context
4592420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4593420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4594420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`)
4595420bcc1bSBarry Smith 
4596420bcc1bSBarry Smith   Calling sequence of `f`:
4597420bcc1bSBarry Smith + snes - the `SNES` context
4598420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function
4599420bcc1bSBarry Smith 
4600420bcc1bSBarry Smith   Calling sequence of `reasonviewerdestroy`:
4601420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function
4602c4421ceaSFande Kong 
4603c4421ceaSFande Kong   Options Database Keys:
4604f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4605420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4606420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4607c4421ceaSFande Kong 
4608dc4c0fb0SBarry Smith   Level: intermediate
4609dc4c0fb0SBarry Smith 
4610f6dfbefdSBarry Smith   Note:
4611c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4612f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4613c4421ceaSFande Kong   order in which they were set.
4614c4421ceaSFande Kong 
46151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4616c4421ceaSFande Kong @*/
4617420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx))
4618d71ae5a4SJacob Faibussowitsch {
4619c4421ceaSFande Kong   PetscInt  i;
4620c4421ceaSFande Kong   PetscBool identical;
4621c4421ceaSFande Kong 
4622c4421ceaSFande Kong   PetscFunctionBegin;
4623c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4624c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
46259566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
46263ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4627c4421ceaSFande Kong   }
46285f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4629c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4630c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4631c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
46323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4633c4421ceaSFande Kong }
4634c4421ceaSFande Kong 
463591f3e32bSBarry Smith /*@
4636420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4637c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
46382a359c20SBarry Smith 
4639c3339decSBarry Smith   Collective
46402a359c20SBarry Smith 
46412fe279fdSBarry Smith   Input Parameter:
4642f6dfbefdSBarry Smith . snes - the `SNES` object
46432a359c20SBarry Smith 
4644f6dfbefdSBarry Smith   Level: advanced
46452a359c20SBarry Smith 
46461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4647f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
46482a359c20SBarry Smith @*/
4649d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4650d71ae5a4SJacob Faibussowitsch {
46512a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
46522a359c20SBarry Smith 
46532a359c20SBarry Smith   PetscFunctionBegin;
46543ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
46552a359c20SBarry Smith   incall = PETSC_TRUE;
4656c4421ceaSFande Kong 
4657c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
465836d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4659c4421ceaSFande Kong 
4660c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
466136d43d94SBarry Smith   if (snes->convergedreasonviewer) {
466236d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
466336d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
466436d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
46652a359c20SBarry Smith   }
46662a359c20SBarry Smith   incall = PETSC_FALSE;
46673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46682a359c20SBarry Smith }
46692a359c20SBarry Smith 
4670487a658cSBarry Smith /*@
4671f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
46729b94acceSBarry Smith 
4673c3339decSBarry Smith   Collective
4674c7afd0dbSLois Curfman McInnes 
4675b2002411SLois Curfman McInnes   Input Parameters:
4676f6dfbefdSBarry Smith + snes - the `SNES` context
4677dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
467885385478SLisandro Dalcin - x    - the solution vector.
46799b94acceSBarry Smith 
4680dc4c0fb0SBarry Smith   Level: beginner
4681dc4c0fb0SBarry Smith 
4682f6dfbefdSBarry Smith   Note:
4683420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4684420bcc1bSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
46858ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4686f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
46878ddd3da0SLois Curfman McInnes 
46881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4689db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4690420bcc1bSBarry Smith           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
46919b94acceSBarry Smith @*/
4692d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4693d71ae5a4SJacob Faibussowitsch {
4694ace3abfcSBarry Smith   PetscBool flg;
4695efd51863SBarry Smith   PetscInt  grid;
46960298fd71SBarry Smith   Vec       xcreated = NULL;
4697caa4e7f2SJed Brown   DM        dm;
4698052efed2SBarry Smith 
46993a40ed3dSBarry Smith   PetscFunctionBegin;
47000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4701a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4702a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47030700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
470485385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
470585385478SLisandro Dalcin 
470634b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
470706fc46c8SMatthew G. Knepley   {
470806fc46c8SMatthew G. Knepley     PetscViewer       viewer;
470906fc46c8SMatthew G. Knepley     PetscViewerFormat format;
47107c88af5aSMatthew G. Knepley     PetscInt          num;
471106fc46c8SMatthew G. Knepley     PetscBool         flg;
471206fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
471306fc46c8SMatthew G. Knepley 
471406fc46c8SMatthew G. Knepley     if (!incall) {
471534b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4716648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
471706fc46c8SMatthew G. Knepley       if (flg) {
471806fc46c8SMatthew G. Knepley         PetscConvEst conv;
471946079b62SMatthew G. Knepley         DM           dm;
472046079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
472146079b62SMatthew G. Knepley         PetscInt     Nf;
472206fc46c8SMatthew G. Knepley 
472306fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
47249566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
47259566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
47269566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
47279566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
47289566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
47299566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
47309566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
47319566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
47329566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
47339566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
47349566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4735648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
47369566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
47379566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
473806fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
473906fc46c8SMatthew G. Knepley       }
474034b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4741b2588ea6SMatthew G. Knepley       num = 1;
47429566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
474334b4d3a8SMatthew G. Knepley       if (flg) {
474434b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
474534b4d3a8SMatthew G. Knepley 
474634b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
47479566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
47489566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
47499566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
47509566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
47519566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
47529566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
47539566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
475434b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
475534b4d3a8SMatthew G. Knepley       }
47567c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
47577c88af5aSMatthew G. Knepley       num = 0;
47589566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
47597c88af5aSMatthew G. Knepley       if (num) {
47607c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4761e03fd340SMatthew G. Knepley         const char *prefix;
47627c88af5aSMatthew G. Knepley 
47637c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
47649566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4765e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4766e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
47679566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
47689566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
47699566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
47709566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4771e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
47729566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
47739566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
47747c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
47757c88af5aSMatthew G. Knepley       }
477606fc46c8SMatthew G. Knepley     }
477706fc46c8SMatthew G. Knepley   }
4778ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4779caa4e7f2SJed Brown   if (!x) {
47809566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
47819566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4782a69afd8bSBarry Smith     x = xcreated;
4783a69afd8bSBarry Smith   }
47849566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4785f05ece33SBarry Smith 
47869566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4787efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
478885385478SLisandro Dalcin     /* set solution vector */
47899566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
47909566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
479185385478SLisandro Dalcin     snes->vec_sol = x;
47929566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4793caa4e7f2SJed Brown 
4794caa4e7f2SJed Brown     /* set affine vector if provided */
47959566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
47969566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
479785385478SLisandro Dalcin     snes->vec_rhs = b;
479885385478SLisandro Dalcin 
47995f80ce2aSJacob 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");
48005f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4801dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4802aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48039566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48049566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48053f149594SLisandro Dalcin 
48067eee914bSBarry Smith     if (!grid) {
48079927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4808dd568438SSatish Balay     }
4809d25893d9SBarry Smith 
4810abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
48119371c9d4SSatish Balay     if (snes->counters_reset) {
48129371c9d4SSatish Balay       snes->nfuncs      = 0;
48139371c9d4SSatish Balay       snes->linear_its  = 0;
48149371c9d4SSatish Balay       snes->numFailures = 0;
48159371c9d4SSatish Balay     }
4816d5e45103SBarry Smith 
48172d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
48189566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4819dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
48209566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
48212d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4822422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
48233f149594SLisandro Dalcin 
482437ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
482537ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
482637ec4e1aSPeter Brune 
4827648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
48289566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4829c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
48309566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
48315968eb51SBarry Smith 
48325f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
48339c8e83a9SBarry Smith     if (snes->reason < 0) break;
4834efd51863SBarry Smith     if (grid < snes->gridsequence) {
4835efd51863SBarry Smith       DM  fine;
4836efd51863SBarry Smith       Vec xnew;
4837efd51863SBarry Smith       Mat interp;
4838efd51863SBarry Smith 
48399566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
48405f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
48419566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
48429566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
48439566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
48449566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
48459566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4846efd51863SBarry Smith       x = xnew;
4847efd51863SBarry Smith 
48489566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
48499566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
48509566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
48519566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
48529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4853efd51863SBarry Smith     }
4854efd51863SBarry Smith   }
48559566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
48569566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
48579566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
48589566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
48593f7e2da0SPeter Brune 
48609566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
48619566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
48623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48639b94acceSBarry Smith }
48649b94acceSBarry Smith 
48659b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
48669b94acceSBarry Smith 
4867cc4c1da9SBarry Smith /*@
48684b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
48699b94acceSBarry Smith 
4870c3339decSBarry Smith   Collective
4871fee21e36SBarry Smith 
4872c7afd0dbSLois Curfman McInnes   Input Parameters:
4873f6dfbefdSBarry Smith + snes - the `SNES` context
4874454a90a3SBarry Smith - type - a known method
4875c7afd0dbSLois Curfman McInnes 
4876c7afd0dbSLois Curfman McInnes   Options Database Key:
4877454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
487804d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4879ae12b187SLois Curfman McInnes 
4880dc4c0fb0SBarry Smith   Level: intermediate
4881dc4c0fb0SBarry Smith 
48829b94acceSBarry Smith   Notes:
4883e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4884f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4885c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
48864a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4887c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
48889b94acceSBarry Smith 
4889f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4890f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4891ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4892ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4893f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4894ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4895ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4896ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4897ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4898b0a32e0cSBarry Smith   appropriate method.
489936851e7fSLois Curfman McInnes 
4900420bcc1bSBarry Smith   Developer Note:
4901f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4902f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
49038f6c3df8SBarry Smith 
49041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49059b94acceSBarry Smith @*/
4906d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4907d71ae5a4SJacob Faibussowitsch {
4908ace3abfcSBarry Smith   PetscBool match;
49095f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
49103a40ed3dSBarry Smith 
49113a40ed3dSBarry Smith   PetscFunctionBegin;
49120700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49134f572ea9SToby Isaac   PetscAssertPointer(type, 2);
491482bf6240SBarry Smith 
49159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
49163ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
491792ff6ae8SBarry Smith 
49189566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
49196adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
492075396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4921dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
492275396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
49239e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
49249e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
49259e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
49269e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
49279e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
49287fe760d5SStefano Zampini 
49297fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
49309566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
49317fe760d5SStefano Zampini 
493275396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
493375396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4934f5af7f23SKarl Rupp 
49359566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
49369566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
49373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49389b94acceSBarry Smith }
49399b94acceSBarry Smith 
4940cc4c1da9SBarry Smith /*@
4941f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
49429b94acceSBarry Smith 
4943c7afd0dbSLois Curfman McInnes   Not Collective
4944c7afd0dbSLois Curfman McInnes 
49459b94acceSBarry Smith   Input Parameter:
49464b0e389bSBarry Smith . snes - nonlinear solver context
49479b94acceSBarry Smith 
49489b94acceSBarry Smith   Output Parameter:
4949f6dfbefdSBarry Smith . type - `SNES` method (a character string)
49509b94acceSBarry Smith 
495136851e7fSLois Curfman McInnes   Level: intermediate
495236851e7fSLois Curfman McInnes 
49531cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
49549b94acceSBarry Smith @*/
4955d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4956d71ae5a4SJacob Faibussowitsch {
49573a40ed3dSBarry Smith   PetscFunctionBegin;
49580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49594f572ea9SToby Isaac   PetscAssertPointer(type, 2);
49607adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
49613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49629b94acceSBarry Smith }
49639b94acceSBarry Smith 
49643cd8a7caSMatthew G. Knepley /*@
4965f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
49663cd8a7caSMatthew G. Knepley 
4967c3339decSBarry Smith   Logically Collective
49683cd8a7caSMatthew G. Knepley 
49693cd8a7caSMatthew G. Knepley   Input Parameters:
4970f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
49713cd8a7caSMatthew G. Knepley - u    - the solution vector
49723cd8a7caSMatthew G. Knepley 
49733cd8a7caSMatthew G. Knepley   Level: beginner
49743cd8a7caSMatthew G. Knepley 
49751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
49763cd8a7caSMatthew G. Knepley @*/
4977d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4978d71ae5a4SJacob Faibussowitsch {
49793cd8a7caSMatthew G. Knepley   DM dm;
49803cd8a7caSMatthew G. Knepley 
49813cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
49823cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49833cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
49849566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
49859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
49863cd8a7caSMatthew G. Knepley 
49873cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
49883cd8a7caSMatthew G. Knepley 
49899566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49909566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
49913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49923cd8a7caSMatthew G. Knepley }
49933cd8a7caSMatthew G. Knepley 
499452baeb72SSatish Balay /*@
49959b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
4996f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
49979b94acceSBarry Smith 
4998420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4999c7afd0dbSLois Curfman McInnes 
50009b94acceSBarry Smith   Input Parameter:
5001f6dfbefdSBarry Smith . snes - the `SNES` context
50029b94acceSBarry Smith 
50039b94acceSBarry Smith   Output Parameter:
50049b94acceSBarry Smith . x - the solution
50059b94acceSBarry Smith 
500670e92668SMatthew Knepley   Level: intermediate
500736851e7fSLois Curfman McInnes 
50081cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
50099b94acceSBarry Smith @*/
5010d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5011d71ae5a4SJacob Faibussowitsch {
50123a40ed3dSBarry Smith   PetscFunctionBegin;
50130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50144f572ea9SToby Isaac   PetscAssertPointer(x, 2);
501585385478SLisandro Dalcin   *x = snes->vec_sol;
50163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
501770e92668SMatthew Knepley }
501870e92668SMatthew Knepley 
501952baeb72SSatish Balay /*@
50209b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
50219b94acceSBarry Smith   stored.
50229b94acceSBarry Smith 
5023420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5024c7afd0dbSLois Curfman McInnes 
50259b94acceSBarry Smith   Input Parameter:
5026f6dfbefdSBarry Smith . snes - the `SNES` context
50279b94acceSBarry Smith 
50289b94acceSBarry Smith   Output Parameter:
50299b94acceSBarry Smith . x - the solution update
50309b94acceSBarry Smith 
503136851e7fSLois Curfman McInnes   Level: advanced
503236851e7fSLois Curfman McInnes 
50331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
50349b94acceSBarry Smith @*/
5035d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5036d71ae5a4SJacob Faibussowitsch {
50373a40ed3dSBarry Smith   PetscFunctionBegin;
50380700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50394f572ea9SToby Isaac   PetscAssertPointer(x, 2);
504085385478SLisandro Dalcin   *x = snes->vec_sol_update;
50413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50429b94acceSBarry Smith }
50439b94acceSBarry Smith 
50449b94acceSBarry Smith /*@C
5045f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
50469b94acceSBarry Smith 
5047420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5048c7afd0dbSLois Curfman McInnes 
50499b94acceSBarry Smith   Input Parameter:
5050f6dfbefdSBarry Smith . snes - the `SNES` context
50519b94acceSBarry Smith 
5052d8d19677SJose E. Roman   Output Parameters:
5053dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
50548434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5055dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
50569b94acceSBarry Smith 
505736851e7fSLois Curfman McInnes   Level: advanced
505836851e7fSLois Curfman McInnes 
5059f6dfbefdSBarry Smith   Note:
5060dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
506104edfde5SBarry Smith 
50628434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
50639b94acceSBarry Smith @*/
50648434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5065d71ae5a4SJacob Faibussowitsch {
50666cab3a1bSJed Brown   DM dm;
5067a63bb30eSJed Brown 
50683a40ed3dSBarry Smith   PetscFunctionBegin;
50690700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5070a63bb30eSJed Brown   if (r) {
5071a63bb30eSJed Brown     if (!snes->vec_func) {
5072a63bb30eSJed Brown       if (snes->vec_rhs) {
50739566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5074a63bb30eSJed Brown       } else if (snes->vec_sol) {
50759566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5076a63bb30eSJed Brown       } else if (snes->dm) {
50779566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5078a63bb30eSJed Brown       }
5079a63bb30eSJed Brown     }
5080a63bb30eSJed Brown     *r = snes->vec_func;
5081a63bb30eSJed Brown   }
50829566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50839566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
50843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50859b94acceSBarry Smith }
50869b94acceSBarry Smith 
5087c79ef259SPeter Brune /*@C
508837fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5089c79ef259SPeter Brune 
5090c79ef259SPeter Brune   Input Parameter:
5091f6dfbefdSBarry Smith . snes - the `SNES` context
5092c79ef259SPeter Brune 
5093d8d19677SJose E. Roman   Output Parameters:
50948434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5095dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5096c79ef259SPeter Brune 
5097c79ef259SPeter Brune   Level: advanced
5098c79ef259SPeter Brune 
50998434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5100c79ef259SPeter Brune @*/
51018434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5102d71ae5a4SJacob Faibussowitsch {
51036cab3a1bSJed Brown   DM dm;
51046cab3a1bSJed Brown 
5105646217ecSPeter Brune   PetscFunctionBegin;
5106646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51079566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51089566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
51093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5110646217ecSPeter Brune }
5111646217ecSPeter Brune 
5112cc4c1da9SBarry Smith /*@
51133c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5114f6dfbefdSBarry Smith   `SNES` options in the database.
51153c7409f5SSatish Balay 
5116c3339decSBarry Smith   Logically Collective
5117fee21e36SBarry Smith 
5118d8d19677SJose E. Roman   Input Parameters:
5119f6dfbefdSBarry Smith + snes   - the `SNES` context
5120c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5121c7afd0dbSLois Curfman McInnes 
5122dc4c0fb0SBarry Smith   Level: advanced
5123dc4c0fb0SBarry Smith 
5124f6dfbefdSBarry Smith   Note:
5125a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5126c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5127d850072dSLois Curfman McInnes 
51281cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
51293c7409f5SSatish Balay @*/
5130d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5131d71ae5a4SJacob Faibussowitsch {
51323a40ed3dSBarry Smith   PetscFunctionBegin;
51330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51349566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
51359566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
513635f5d045SPeter Brune   if (snes->linesearch) {
51379566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51389566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
513935f5d045SPeter Brune   }
51409566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
51413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51423c7409f5SSatish Balay }
51433c7409f5SSatish Balay 
5144cc4c1da9SBarry Smith /*@
5145f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5146f6dfbefdSBarry Smith   `SNES` options in the database.
51473c7409f5SSatish Balay 
5148c3339decSBarry Smith   Logically Collective
5149fee21e36SBarry Smith 
5150c7afd0dbSLois Curfman McInnes   Input Parameters:
5151f6dfbefdSBarry Smith + snes   - the `SNES` context
5152c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5153c7afd0dbSLois Curfman McInnes 
5154dc4c0fb0SBarry Smith   Level: advanced
5155dc4c0fb0SBarry Smith 
5156f6dfbefdSBarry Smith   Note:
5157a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5158c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5159d850072dSLois Curfman McInnes 
51601cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
51613c7409f5SSatish Balay @*/
5162d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5163d71ae5a4SJacob Faibussowitsch {
51643a40ed3dSBarry Smith   PetscFunctionBegin;
51650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51669566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
51679566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
516835f5d045SPeter Brune   if (snes->linesearch) {
51699566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51709566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
517135f5d045SPeter Brune   }
51729566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
51733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51743c7409f5SSatish Balay }
51753c7409f5SSatish Balay 
5176cc4c1da9SBarry Smith /*@
5177f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5178f6dfbefdSBarry Smith   `SNES` options in the database.
51793c7409f5SSatish Balay 
5180c7afd0dbSLois Curfman McInnes   Not Collective
5181c7afd0dbSLois Curfman McInnes 
51823c7409f5SSatish Balay   Input Parameter:
5183f6dfbefdSBarry Smith . snes - the `SNES` context
51843c7409f5SSatish Balay 
51853c7409f5SSatish Balay   Output Parameter:
51863c7409f5SSatish Balay . prefix - pointer to the prefix string used
51873c7409f5SSatish Balay 
518836851e7fSLois Curfman McInnes   Level: advanced
518936851e7fSLois Curfman McInnes 
5190420bcc1bSBarry Smith   Fortran Note:
5191dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5192dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5193dc4c0fb0SBarry Smith 
51941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
51953c7409f5SSatish Balay @*/
5196d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5197d71ae5a4SJacob Faibussowitsch {
51983a40ed3dSBarry Smith   PetscFunctionBegin;
51990700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52009566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52023c7409f5SSatish Balay }
52033c7409f5SSatish Balay 
52043cea93caSBarry Smith /*@C
52051c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
52061c84c290SBarry Smith 
520720f4b53cSBarry Smith   Not Collective
52081c84c290SBarry Smith 
52091c84c290SBarry Smith   Input Parameters:
521020f4b53cSBarry Smith + sname    - name of a new user-defined solver
521120f4b53cSBarry Smith - function - routine to create method context
52121c84c290SBarry Smith 
5213dc4c0fb0SBarry Smith   Level: advanced
5214dc4c0fb0SBarry Smith 
5215f6dfbefdSBarry Smith   Note:
5216f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
52171c84c290SBarry Smith 
5218e4094ef1SJacob Faibussowitsch   Example Usage:
52191c84c290SBarry Smith .vb
5220bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
52211c84c290SBarry Smith .ve
52221c84c290SBarry Smith 
52231c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
52241c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
52251c84c290SBarry Smith   or at runtime via the option
52261c84c290SBarry Smith $     -snes_type my_solver
52271c84c290SBarry Smith 
52281cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
52293cea93caSBarry Smith @*/
5230d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5231d71ae5a4SJacob Faibussowitsch {
5232b2002411SLois Curfman McInnes   PetscFunctionBegin;
52339566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
52349566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
52353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5236b2002411SLois Curfman McInnes }
5237da9b6338SBarry Smith 
5238d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5239d71ae5a4SJacob Faibussowitsch {
524077431f27SBarry Smith   PetscInt    N, i, j;
5241da9b6338SBarry Smith   Vec         u, uh, fh;
5242da9b6338SBarry Smith   PetscScalar value;
5243da9b6338SBarry Smith   PetscReal   norm;
5244da9b6338SBarry Smith 
5245da9b6338SBarry Smith   PetscFunctionBegin;
52469566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
52479566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
52489566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5249da9b6338SBarry Smith 
5250da9b6338SBarry Smith   /* currently only works for sequential */
52519566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
52529566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5253da9b6338SBarry Smith   for (i = 0; i < N; i++) {
52549566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
525563a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5256da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
52578b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
52589566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
52599566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
52609566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
526163a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5262da9b6338SBarry Smith       value = -value;
52639566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5264da9b6338SBarry Smith     }
5265da9b6338SBarry Smith   }
52669566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
52679566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
52683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5269da9b6338SBarry Smith }
527071f87433Sdalcinl 
527171f87433Sdalcinl /*@
5272f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
527371f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
527471f87433Sdalcinl   Newton method.
527571f87433Sdalcinl 
5276c3339decSBarry Smith   Logically Collective
527771f87433Sdalcinl 
527871f87433Sdalcinl   Input Parameters:
5279f6dfbefdSBarry Smith + snes - `SNES` context
5280f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
528171f87433Sdalcinl 
5282f6dfbefdSBarry Smith   Options Database Keys:
528364ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
528464ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
528564ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
528664ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
528764ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
528864ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
528964ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
529064ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
529164ba62caSBarry Smith 
5292dc4c0fb0SBarry Smith   Level: advanced
5293dc4c0fb0SBarry Smith 
5294f6dfbefdSBarry Smith   Note:
5295f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
529671f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
52971d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
529871f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
529971f87433Sdalcinl   solver.
530071f87433Sdalcinl 
53011cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
530271f87433Sdalcinl @*/
5303d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5304d71ae5a4SJacob Faibussowitsch {
530571f87433Sdalcinl   PetscFunctionBegin;
53060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5307acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
530871f87433Sdalcinl   snes->ksp_ewconv = flag;
53093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
531071f87433Sdalcinl }
531171f87433Sdalcinl 
531271f87433Sdalcinl /*@
5313f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
531471f87433Sdalcinl   for computing relative tolerance for linear solvers within an
531571f87433Sdalcinl   inexact Newton method.
531671f87433Sdalcinl 
531771f87433Sdalcinl   Not Collective
531871f87433Sdalcinl 
531971f87433Sdalcinl   Input Parameter:
5320f6dfbefdSBarry Smith . snes - `SNES` context
532171f87433Sdalcinl 
532271f87433Sdalcinl   Output Parameter:
5323f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
532471f87433Sdalcinl 
532571f87433Sdalcinl   Level: advanced
532671f87433Sdalcinl 
53271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
532871f87433Sdalcinl @*/
5329d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5330d71ae5a4SJacob Faibussowitsch {
533171f87433Sdalcinl   PetscFunctionBegin;
53320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
53334f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
533471f87433Sdalcinl   *flag = snes->ksp_ewconv;
53353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
533671f87433Sdalcinl }
533771f87433Sdalcinl 
533871f87433Sdalcinl /*@
5339fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
534071f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
534171f87433Sdalcinl   Newton method.
534271f87433Sdalcinl 
5343c3339decSBarry Smith   Logically Collective
534471f87433Sdalcinl 
534571f87433Sdalcinl   Input Parameters:
5346f6dfbefdSBarry Smith + snes      - `SNES` context
53470f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
534871f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
534971f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
535071f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
535171f87433Sdalcinl              (0 <= gamma2 <= 1)
535271f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
535371f87433Sdalcinl . alpha2    - power for safeguard
535471f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
535571f87433Sdalcinl 
5356dc4c0fb0SBarry Smith   Level: advanced
5357dc4c0fb0SBarry Smith 
5358f6dfbefdSBarry Smith   Notes:
535971f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
536071f87433Sdalcinl 
536177e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
536271f87433Sdalcinl 
53631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
536471f87433Sdalcinl @*/
5365d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5366d71ae5a4SJacob Faibussowitsch {
5367fa9f3622SBarry Smith   SNESKSPEW *kctx;
53685fd66863SKarl Rupp 
536971f87433Sdalcinl   PetscFunctionBegin;
53700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5371fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53725f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5373c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5374c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5375c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5376c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5377c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5378c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5379c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
538071f87433Sdalcinl 
538177e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
538277e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
538377e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
538477e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
538577e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
538677e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
538777e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
538871f87433Sdalcinl 
53890f0abf79SStefano 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);
53900b121fc5SBarry 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);
53910b121fc5SBarry 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);
53920b121fc5SBarry 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);
53930b121fc5SBarry 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);
53940b121fc5SBarry 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);
53953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
539671f87433Sdalcinl }
539771f87433Sdalcinl 
539871f87433Sdalcinl /*@
5399fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
540071f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
540171f87433Sdalcinl   Newton method.
540271f87433Sdalcinl 
540371f87433Sdalcinl   Not Collective
540471f87433Sdalcinl 
540597bb3fdcSJose E. Roman   Input Parameter:
5406f6dfbefdSBarry Smith . snes - `SNES` context
540771f87433Sdalcinl 
540871f87433Sdalcinl   Output Parameters:
54090f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
541071f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
541171f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5412bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
541371f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
541471f87433Sdalcinl . alpha2    - power for safeguard
541571f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
541671f87433Sdalcinl 
541771f87433Sdalcinl   Level: advanced
541871f87433Sdalcinl 
54191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
542071f87433Sdalcinl @*/
5421d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5422d71ae5a4SJacob Faibussowitsch {
5423fa9f3622SBarry Smith   SNESKSPEW *kctx;
54245fd66863SKarl Rupp 
542571f87433Sdalcinl   PetscFunctionBegin;
54260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5427fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54285f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
542971f87433Sdalcinl   if (version) *version = kctx->version;
543071f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
543171f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
543271f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
543371f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
543471f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
543571f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
54363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
543771f87433Sdalcinl }
543871f87433Sdalcinl 
54395c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5440d71ae5a4SJacob Faibussowitsch {
54415c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5442fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
544377e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
544471f87433Sdalcinl 
544571f87433Sdalcinl   PetscFunctionBegin;
54463ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
544730058271SDmitry Karpeev   if (!snes->iter) {
544830058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
54499566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
54500f0abf79SStefano Zampini   } else {
54510fdf79fbSJacob 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);
545271f87433Sdalcinl     if (kctx->version == 1) {
54530f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
545485ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
545571f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
545671f87433Sdalcinl     } else if (kctx->version == 2) {
545785ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
545885ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
545971f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
546071f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
546185ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
546271f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
546385ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
546471f87433Sdalcinl       stol = PetscMax(rtol, stol);
546571f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
546671f87433Sdalcinl       /* safeguard: avoid oversolving */
546730058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
546871f87433Sdalcinl       stol = PetscMax(rtol, stol);
546971f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
54700fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
54710fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
54720f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
54730f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
54740f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
54750f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
54760f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
54770f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
54780f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
54790f0abf79SStefano Zampini 
5480a4598233SStefano 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;
54810f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
54820f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
54830f0abf79SStefano Zampini       kctx->rk_last     = rk;
54840fdf79fbSJacob Faibussowitsch     }
54850f0abf79SStefano Zampini   }
54860f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
548771f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
548877e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
548963a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
54903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
549171f87433Sdalcinl }
549271f87433Sdalcinl 
54935c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5494d71ae5a4SJacob Faibussowitsch {
54955c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5496fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
549771f87433Sdalcinl   PCSide     pcside;
549871f87433Sdalcinl   Vec        lres;
549971f87433Sdalcinl 
550071f87433Sdalcinl   PetscFunctionBegin;
55013ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
55029566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
550371dbe336SPeter Brune   kctx->norm_last = snes->norm;
55040f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
55054f00ce20SMatthew G. Knepley     PC        pc;
55060f0abf79SStefano Zampini     PetscBool getRes;
55074f00ce20SMatthew G. Knepley 
55089566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
55090f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
55100f0abf79SStefano Zampini     if (!getRes) {
55110f0abf79SStefano Zampini       KSPNormType normtype;
55120f0abf79SStefano Zampini 
55130f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
55140f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
55150f0abf79SStefano Zampini     }
55169566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
55170f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
55189566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
551971f87433Sdalcinl     } else {
552071f87433Sdalcinl       /* KSP residual is preconditioned residual */
552171f87433Sdalcinl       /* compute true linear residual norm */
55220f0abf79SStefano Zampini       Mat J;
55230f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
55249566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
55250f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
55269566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
55279566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
55289566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
552971f87433Sdalcinl     }
553071f87433Sdalcinl   }
55313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
553271f87433Sdalcinl }
553371f87433Sdalcinl 
5534d4211eb9SBarry Smith /*@
5535f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5536d4211eb9SBarry Smith 
5537420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5538d4211eb9SBarry Smith 
5539d4211eb9SBarry Smith   Input Parameter:
5540f6dfbefdSBarry Smith . snes - the `SNES` context
5541d4211eb9SBarry Smith 
5542d4211eb9SBarry Smith   Output Parameter:
5543f6dfbefdSBarry Smith . ksp - the `KSP` context
5544d4211eb9SBarry Smith 
5545dc4c0fb0SBarry Smith   Level: beginner
5546dc4c0fb0SBarry Smith 
5547d4211eb9SBarry Smith   Notes:
5548f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5549d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5550f6dfbefdSBarry Smith   `PC` contexts as well.
5551f6dfbefdSBarry Smith 
5552f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5553d4211eb9SBarry Smith 
55541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5555d4211eb9SBarry Smith @*/
5556d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5557d71ae5a4SJacob Faibussowitsch {
555871f87433Sdalcinl   PetscFunctionBegin;
5559d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55604f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5561d4211eb9SBarry Smith 
5562d4211eb9SBarry Smith   if (!snes->ksp) {
55639566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
55649566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5565d4211eb9SBarry Smith 
55665c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
55675c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5568a5c2985bSBarry Smith 
55699566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
55709566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5571d4211eb9SBarry Smith   }
5572d4211eb9SBarry Smith   *ksp = snes->ksp;
55733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
557471f87433Sdalcinl }
55756c699258SBarry Smith 
5576af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
55776c699258SBarry Smith /*@
5578f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
55796c699258SBarry Smith 
5580c3339decSBarry Smith   Logically Collective
55816c699258SBarry Smith 
55826c699258SBarry Smith   Input Parameters:
55832a808120SBarry Smith + snes - the nonlinear solver context
5584420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5585dc4c0fb0SBarry Smith 
5586dc4c0fb0SBarry Smith   Level: intermediate
55876c699258SBarry Smith 
5588f6dfbefdSBarry Smith   Note:
5589f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5590f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5591e03a659cSJed Brown   problems using the same function space.
5592e03a659cSJed Brown 
5593420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
55946c699258SBarry Smith @*/
5595d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5596d71ae5a4SJacob Faibussowitsch {
5597345fed2cSBarry Smith   KSP    ksp;
5598942e3340SBarry Smith   DMSNES sdm;
55996c699258SBarry Smith 
56006c699258SBarry Smith   PetscFunctionBegin;
56010700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56022a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
56039566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5604942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
560551f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
56069566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
56079566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5608f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
56096cab3a1bSJed Brown     }
56109566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
56119566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
56126cab3a1bSJed Brown   }
56136c699258SBarry Smith   snes->dm     = dm;
5614116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5615f5af7f23SKarl Rupp 
56169566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
56179566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
56189566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5619efd4aadfSBarry Smith   if (snes->npc) {
56209566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
56219566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
56222c155ee1SBarry Smith   }
56233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56246c699258SBarry Smith }
56256c699258SBarry Smith 
56266c699258SBarry Smith /*@
5627420bcc1bSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners
56286c699258SBarry Smith 
5629f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
56306c699258SBarry Smith 
56316c699258SBarry Smith   Input Parameter:
5632420bcc1bSBarry Smith . snes - the `SNES` context
56336c699258SBarry Smith 
56346c699258SBarry Smith   Output Parameter:
5635420bcc1bSBarry Smith . dm - the `DM`
56366c699258SBarry Smith 
56376c699258SBarry Smith   Level: intermediate
56386c699258SBarry Smith 
5639420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
56406c699258SBarry Smith @*/
5641d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5642d71ae5a4SJacob Faibussowitsch {
56436c699258SBarry Smith   PetscFunctionBegin;
56440700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56456cab3a1bSJed Brown   if (!snes->dm) {
56469566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5647116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
56486cab3a1bSJed Brown   }
56496c699258SBarry Smith   *dm = snes->dm;
56503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56516c699258SBarry Smith }
56520807856dSBarry Smith 
565331823bd8SMatthew G Knepley /*@
5654be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
565531823bd8SMatthew G Knepley 
5656c3339decSBarry Smith   Collective
565731823bd8SMatthew G Knepley 
565831823bd8SMatthew G Knepley   Input Parameters:
5659f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5660420bcc1bSBarry Smith - npc  - the nonlinear preconditioner object
566131823bd8SMatthew G Knepley 
5662dc4c0fb0SBarry Smith   Level: developer
5663dc4c0fb0SBarry Smith 
566431823bd8SMatthew G Knepley   Notes:
5665f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
566631823bd8SMatthew G Knepley   to configure it using the API).
566731823bd8SMatthew G Knepley 
5668f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5669f6dfbefdSBarry Smith 
5670420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
567131823bd8SMatthew G Knepley @*/
5672d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5673d71ae5a4SJacob Faibussowitsch {
567431823bd8SMatthew G Knepley   PetscFunctionBegin;
567531823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5676f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5677f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5678f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
56799566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5680f6dfbefdSBarry Smith   snes->npc = npc;
56813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
568231823bd8SMatthew G Knepley }
568331823bd8SMatthew G Knepley 
568431823bd8SMatthew G Knepley /*@
5685f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
568631823bd8SMatthew G Knepley 
5687f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
568831823bd8SMatthew G Knepley 
568931823bd8SMatthew G Knepley   Input Parameter:
5690f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
569131823bd8SMatthew G Knepley 
569231823bd8SMatthew G Knepley   Output Parameter:
5693e4094ef1SJacob Faibussowitsch . pc - preconditioner context
569431823bd8SMatthew G Knepley 
5695f6dfbefdSBarry Smith   Options Database Key:
5696f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5697b5badacbSBarry Smith 
5698dc4c0fb0SBarry Smith   Level: developer
5699dc4c0fb0SBarry Smith 
570095452b02SPatrick Sanan   Notes:
5701f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5702be95d8f1SBarry Smith 
5703f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5704f6dfbefdSBarry Smith   `SNES`
5705951fe5abSBarry Smith 
57061cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
570731823bd8SMatthew G Knepley @*/
5708d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5709d71ae5a4SJacob Faibussowitsch {
5710a64e098fSPeter Brune   const char *optionsprefix;
571131823bd8SMatthew G Knepley 
571231823bd8SMatthew G Knepley   PetscFunctionBegin;
571331823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57144f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5715efd4aadfSBarry Smith   if (!snes->npc) {
5716ec785e5bSStefano Zampini     void *ctx;
5717ec785e5bSStefano Zampini 
57189566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
57199566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
57209566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57219566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
57229566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5723fb87a551SStefano Zampini     if (snes->ops->usercompute) {
5724fb87a551SStefano Zampini       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy));
5725fb87a551SStefano Zampini     } else {
5726ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5727ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5728fb87a551SStefano Zampini     }
57299566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
573031823bd8SMatthew G Knepley   }
5731efd4aadfSBarry Smith   *pc = snes->npc;
57323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
573331823bd8SMatthew G Knepley }
573431823bd8SMatthew G Knepley 
57353ad1a0b9SPatrick Farrell /*@
57363ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
57373ad1a0b9SPatrick Farrell 
57383ad1a0b9SPatrick Farrell   Not Collective
57393ad1a0b9SPatrick Farrell 
57403ad1a0b9SPatrick Farrell   Input Parameter:
5741f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57423ad1a0b9SPatrick Farrell 
57433ad1a0b9SPatrick Farrell   Output Parameter:
5744420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
57453ad1a0b9SPatrick Farrell 
57463ad1a0b9SPatrick Farrell   Level: developer
57473ad1a0b9SPatrick Farrell 
57481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
57493ad1a0b9SPatrick Farrell @*/
5750d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5751d71ae5a4SJacob Faibussowitsch {
57523ad1a0b9SPatrick Farrell   PetscFunctionBegin;
57533ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5754efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
57553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57563ad1a0b9SPatrick Farrell }
57573ad1a0b9SPatrick Farrell 
5758c40d0f55SPeter Brune /*@
5759420bcc1bSBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side.
5760c40d0f55SPeter Brune 
5761c3339decSBarry Smith   Logically Collective
5762c40d0f55SPeter Brune 
5763c40d0f55SPeter Brune   Input Parameter:
5764f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5765c40d0f55SPeter Brune 
5766c40d0f55SPeter Brune   Output Parameter:
5767c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5768c40d0f55SPeter Brune .vb
57692d547940SBarry Smith       PC_LEFT - left preconditioning
57702d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5771c40d0f55SPeter Brune .ve
5772c40d0f55SPeter Brune 
5773f6dfbefdSBarry Smith   Options Database Key:
577467b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5775c40d0f55SPeter Brune 
5776dc4c0fb0SBarry Smith   Level: intermediate
5777dc4c0fb0SBarry Smith 
5778f6dfbefdSBarry Smith   Note:
5779f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
57802d547940SBarry Smith 
5781420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5782c40d0f55SPeter Brune @*/
5783d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5784d71ae5a4SJacob Faibussowitsch {
5785c40d0f55SPeter Brune   PetscFunctionBegin;
5786c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5787c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5788b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
578954c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5790efd4aadfSBarry Smith   snes->npcside = side;
57913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5792c40d0f55SPeter Brune }
5793c40d0f55SPeter Brune 
5794c40d0f55SPeter Brune /*@
5795be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5796c40d0f55SPeter Brune 
5797c40d0f55SPeter Brune   Not Collective
5798c40d0f55SPeter Brune 
5799c40d0f55SPeter Brune   Input Parameter:
5800f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5801c40d0f55SPeter Brune 
5802c40d0f55SPeter Brune   Output Parameter:
5803c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5804c40d0f55SPeter Brune .vb
5805f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5806f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5807c40d0f55SPeter Brune .ve
5808c40d0f55SPeter Brune 
5809c40d0f55SPeter Brune   Level: intermediate
5810c40d0f55SPeter Brune 
5811420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5812c40d0f55SPeter Brune @*/
5813d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5814d71ae5a4SJacob Faibussowitsch {
5815c40d0f55SPeter Brune   PetscFunctionBegin;
5816c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58174f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5818efd4aadfSBarry Smith   *side = snes->npcside;
58193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5820c40d0f55SPeter Brune }
5821c40d0f55SPeter Brune 
58229e764e56SPeter Brune /*@
5823420bcc1bSBarry Smith   SNESSetLineSearch - Sets the linesearch to be used for `SNES`
58249e764e56SPeter Brune 
5825c3339decSBarry Smith   Collective
58269e764e56SPeter Brune 
58279e764e56SPeter Brune   Input Parameters:
5828f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
58299e764e56SPeter Brune - linesearch - the linesearch object
58309e764e56SPeter Brune 
5831dc4c0fb0SBarry Smith   Level: developer
5832dc4c0fb0SBarry Smith 
5833f6dfbefdSBarry Smith   Note:
5834420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
58359e764e56SPeter Brune   to configure it using the API).
58369e764e56SPeter Brune 
5837420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
58389e764e56SPeter Brune @*/
5839d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5840d71ae5a4SJacob Faibussowitsch {
58419e764e56SPeter Brune   PetscFunctionBegin;
58429e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5843f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
58449e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
58459566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
58469566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5847f5af7f23SKarl Rupp 
58489e764e56SPeter Brune   snes->linesearch = linesearch;
58493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58509e764e56SPeter Brune }
58519e764e56SPeter Brune 
5852a34ceb2aSJed Brown /*@
5853420bcc1bSBarry Smith   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5854f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
58559e764e56SPeter Brune 
58569e764e56SPeter Brune   Not Collective
58579e764e56SPeter Brune 
58589e764e56SPeter Brune   Input Parameter:
5859f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58609e764e56SPeter Brune 
58619e764e56SPeter Brune   Output Parameter:
58629e764e56SPeter Brune . linesearch - linesearch context
58639e764e56SPeter Brune 
5864162e0bf5SPeter Brune   Level: beginner
58659e764e56SPeter Brune 
58661cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
58679e764e56SPeter Brune @*/
5868d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5869d71ae5a4SJacob Faibussowitsch {
58709e764e56SPeter Brune   const char *optionsprefix;
58719e764e56SPeter Brune 
58729e764e56SPeter Brune   PetscFunctionBegin;
58739e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58744f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
58759e764e56SPeter Brune   if (!snes->linesearch) {
58769566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
58779566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
58789566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
58799566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
58809566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
58819e764e56SPeter Brune   }
58829e764e56SPeter Brune   *linesearch = snes->linesearch;
58833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58849e764e56SPeter Brune }
5885