xref: /petsc/src/snes/interface/snes.c (revision cbf8f02cb94fab312fccd1cc966a539b13bb1f3c)
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
6187addb90fSBarry Smith        matrix-free version but still employs the user-provided matrix used for computing the preconditioner. */
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 
808d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscMonitorPauseFinal_Internal(PetscInt, void *);
809ce78bad3SBarry Smith 
810d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
811d71ae5a4SJacob Faibussowitsch {
8125e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8133ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
814ce78bad3SBarry Smith   PetscCall(PetscMonitorPauseFinal_Internal(snes->numbermonitors, snes->monitorcontext));
8153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8165e7c47f3SMatthew G. Knepley }
8175e7c47f3SMatthew G. Knepley 
818fde5950dSBarry Smith /*@C
819fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
820fde5950dSBarry Smith 
821c3339decSBarry Smith   Collective
822fde5950dSBarry Smith 
823fde5950dSBarry Smith   Input Parameters:
824dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
825fde5950dSBarry Smith . name         - the monitor type one is seeking
826fde5950dSBarry Smith . help         - message indicating what monitoring is done
827fde5950dSBarry Smith . manual       - manual page for the monitor
82849abdd8aSBarry Smith . monitor      - the monitor function, this must use a `PetscViewerFormat` as its context
829f6dfbefdSBarry 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
830fde5950dSBarry Smith 
831420bcc1bSBarry Smith   Calling sequence of `monitor`:
832420bcc1bSBarry Smith + snes - the nonlinear solver context
833420bcc1bSBarry Smith . it   - the current iteration
834420bcc1bSBarry Smith . r    - the current function norm
835420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
836420bcc1bSBarry Smith 
837420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
838420bcc1bSBarry Smith + snes - the nonlinear solver context
839420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
840420bcc1bSBarry Smith 
841f6dfbefdSBarry Smith   Options Database Key:
842f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
843f6dfbefdSBarry Smith 
844f6dfbefdSBarry Smith   Level: advanced
845fde5950dSBarry Smith 
846648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
847db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
848e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
849db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
850c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
851db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
852db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
853fde5950dSBarry Smith @*/
854420bcc1bSBarry 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))
855d71ae5a4SJacob Faibussowitsch {
856fde5950dSBarry Smith   PetscViewer       viewer;
857fde5950dSBarry Smith   PetscViewerFormat format;
858fde5950dSBarry Smith   PetscBool         flg;
859fde5950dSBarry Smith 
860fde5950dSBarry Smith   PetscFunctionBegin;
861648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
862fde5950dSBarry Smith   if (flg) {
863d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8649566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
865648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
8661baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
86749abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
868fde5950dSBarry Smith   }
8693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
870fde5950dSBarry Smith }
871fde5950dSBarry Smith 
872a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
873d71ae5a4SJacob Faibussowitsch {
874a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
875a4598233SStefano Zampini 
8760f0abf79SStefano Zampini   PetscFunctionBegin;
8770f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
878a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
879a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
880a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
881a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
882a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
883a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
8840f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
885a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
8860f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8870f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8880f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8890f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8900f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8910f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8920f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8930f0abf79SStefano Zampini   PetscOptionsEnd();
8943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8950f0abf79SStefano Zampini }
8960f0abf79SStefano Zampini 
8979b94acceSBarry Smith /*@
898f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
8999b94acceSBarry Smith 
900c3339decSBarry Smith   Collective
901c7afd0dbSLois Curfman McInnes 
9029b94acceSBarry Smith   Input Parameter:
903f6dfbefdSBarry Smith . snes - the `SNES` context
9049b94acceSBarry Smith 
90536851e7fSLois Curfman McInnes   Options Database Keys:
906f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
907b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
90877e5a1f9SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
90977e5a1f9SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
910e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
911b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
912b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
91377e5a1f9SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
9144839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
915ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
916a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9173d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
918e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9193d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
920ceaaa498SBarry 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.
921fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
922fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
923fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
924fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9254619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
926459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9275e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
928e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
929e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
930ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
931b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
932ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
933e62ac41dSBarry 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.
934e62ac41dSBarry 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.
93582738288SBarry Smith 
936f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
937fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9384b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
93936851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
94036851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
94136851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
94236851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
94336851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
94436851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
94582738288SBarry Smith 
946dc4c0fb0SBarry Smith   Level: beginner
947dc4c0fb0SBarry Smith 
94811ca99fdSLois Curfman McInnes   Notes:
949ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
950ec5066bdSBarry Smith 
951420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
952420bcc1bSBarry Smith   and computing explicitly with
953f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
95483e2fdc7SBarry Smith 
955420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9569b94acceSBarry Smith @*/
957d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
958d71ae5a4SJacob Faibussowitsch {
9598afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
96077e5a1f9SBarry Smith   PetscInt    i, indx, lag, grids, max_its, max_funcs;
96104d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
962649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
96385385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9640f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
965c40d0f55SPeter Brune   PCSide      pcside;
966a64e098fSPeter Brune   const char *optionsprefix;
96777e5a1f9SBarry Smith   PetscReal   rtol, abstol, stol;
9689b94acceSBarry Smith 
9693a40ed3dSBarry Smith   PetscFunctionBegin;
9700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9719566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
972d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
973639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
975d64ed03dSBarry Smith   if (flg) {
9769566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9777adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9789566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
979d64ed03dSBarry Smith   }
980186905e3SBarry Smith 
98177e5a1f9SBarry Smith   abstol    = snes->abstol;
98277e5a1f9SBarry Smith   rtol      = snes->rtol;
98377e5a1f9SBarry Smith   stol      = snes->stol;
98477e5a1f9SBarry Smith   max_its   = snes->max_its;
98577e5a1f9SBarry Smith   max_funcs = snes->max_funcs;
98677e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL));
98777e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL));
98877e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL));
98977e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL));
99077e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL));
99177e5a1f9SBarry Smith   PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs));
99277e5a1f9SBarry Smith 
99377e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg));
99477e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol));
99577e5a1f9SBarry Smith 
99677e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg));
99777e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures));
99877e5a1f9SBarry Smith 
99977e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg));
100077e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures));
100177e5a1f9SBarry Smith 
10029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
100585385478SLisandro Dalcin 
10069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1007a8054027SBarry Smith   if (flg) {
10085f80ce2aSJacob 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");
10099566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1010a8054027SBarry Smith   }
10119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10121baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1014e35cf81dSBarry Smith   if (flg) {
10155f80ce2aSJacob 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");
10169566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1017e35cf81dSBarry Smith   }
10189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10191baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
102037ec4e1aSPeter Brune 
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10221baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1023a8054027SBarry Smith 
1024400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
102585385478SLisandro Dalcin   if (flg) {
102685385478SLisandro Dalcin     switch (indx) {
1027d71ae5a4SJacob Faibussowitsch     case 0:
1028d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1029d71ae5a4SJacob Faibussowitsch       break;
1030d71ae5a4SJacob Faibussowitsch     case 1:
1031d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1032d71ae5a4SJacob Faibussowitsch       break;
1033d71ae5a4SJacob Faibussowitsch     case 2:
1034d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1035d71ae5a4SJacob Faibussowitsch       break;
103685385478SLisandro Dalcin     }
103785385478SLisandro Dalcin   }
103885385478SLisandro Dalcin 
10399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10409566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1041fdacfa88SPeter Brune 
10429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10439566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1044186905e3SBarry Smith 
104585385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
104685385478SLisandro Dalcin 
10479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1048186905e3SBarry Smith 
10490f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10500f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1051a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1052186905e3SBarry Smith 
105390d69ab7SBarry Smith   flg = PETSC_FALSE;
10549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10559566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1056eabae89aSBarry Smith 
10579566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10589566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10599566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1060eabae89aSBarry Smith 
10619566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10629566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10639566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10649566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10659566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10669566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10679566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10692db13446SMatthew G. Knepley 
10709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10719566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10725180491cSLisandro Dalcin 
107390d69ab7SBarry Smith   flg = PETSC_FALSE;
10749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1075459f5d12SBarry Smith   if (flg) {
1076459f5d12SBarry Smith     PetscViewer ctx;
1077e24b481bSBarry Smith 
10789566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
107949abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy));
1080459f5d12SBarry Smith   }
10812e7541e6SPeter Brune 
1082648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1083648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
108490d69ab7SBarry Smith   flg = PETSC_FALSE;
10859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10869566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1087c4421ceaSFande Kong 
1088c4421ceaSFande Kong   flg = PETSC_FALSE;
10899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10904b27c08aSLois Curfman McInnes   if (flg) {
10916cab3a1bSJed Brown     void *functx;
1092b1f624c7SBarry Smith     DM    dm;
10939566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1094800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10959566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10969566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10979566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
10989b94acceSBarry Smith   }
1099639f9d9dSBarry Smith 
110044848bc4SPeter Brune   flg = PETSC_FALSE;
11019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11021baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
110397584545SPeter Brune 
110497584545SPeter Brune   flg = PETSC_FALSE;
11059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
110644848bc4SPeter Brune   if (flg) {
1107c52e227fSPeter Brune     DM dm;
11089566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1109800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11109566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11119566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
111244848bc4SPeter Brune   }
111344848bc4SPeter Brune 
1114aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11157addb90fSBarry Smith   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1116d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1117a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1118d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1119a8248277SBarry Smith   }
1120aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11217addb90fSBarry Smith   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no matrix for computing the preconditioner", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1122d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1124d28543b3SPeter Brune 
1125c40d0f55SPeter Brune   flg = PETSC_FALSE;
11269566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11289566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1129c40d0f55SPeter Brune 
1130e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11318a70d858SHong Zhang   /*
11328a70d858SHong Zhang     Publish convergence information using SAWs
11338a70d858SHong Zhang   */
11348a70d858SHong Zhang   flg = PETSC_FALSE;
11359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11368a70d858SHong Zhang   if (flg) {
11378a70d858SHong Zhang     void *ctx;
11389566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11399566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11408a70d858SHong Zhang   }
11418a70d858SHong Zhang #endif
11428a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1143b90c6cbeSBarry Smith   {
1144b90c6cbeSBarry Smith     PetscBool set;
1145b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11469566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11471baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1148b90c6cbeSBarry Smith   }
1149b90c6cbeSBarry Smith #endif
1150b90c6cbeSBarry Smith 
115148a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
115276b2cf59SMatthew Knepley 
1153dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11545d973c19SBarry Smith 
11555d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1156dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1157d0609cedSBarry Smith   PetscOptionsEnd();
11584bbc92c1SBarry Smith 
1159d8d34be6SBarry Smith   if (snes->linesearch) {
11609566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11619566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1162d8d34be6SBarry Smith   }
11639e764e56SPeter Brune 
11646aa5e7e9SBarry Smith   if (snes->usesksp) {
11659566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11669566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11679566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11686aa5e7e9SBarry Smith   }
11696991f827SBarry Smith 
1170b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11719566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
117348a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11741baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1175b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1177b3cd9a81SMatthew G. Knepley }
1178b3cd9a81SMatthew G. Knepley 
1179b3cd9a81SMatthew G. Knepley /*@
1180420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1181b3cd9a81SMatthew G. Knepley 
1182c3339decSBarry Smith   Collective
1183b3cd9a81SMatthew G. Knepley 
1184b3cd9a81SMatthew G. Knepley   Input Parameter:
1185f6dfbefdSBarry Smith . snes - the `SNES` context
1186b3cd9a81SMatthew G. Knepley 
1187420bcc1bSBarry Smith   Level: advanced
1188b3cd9a81SMatthew G. Knepley 
11891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1190b3cd9a81SMatthew G. Knepley @*/
1191d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1192d71ae5a4SJacob Faibussowitsch {
1193b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11949566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11969b94acceSBarry Smith }
11979b94acceSBarry Smith 
1198bb9467b5SJed Brown /*@C
1199d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1200d25893d9SBarry Smith   the nonlinear solvers.
1201d25893d9SBarry Smith 
1202dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1203d25893d9SBarry Smith 
1204d25893d9SBarry Smith   Input Parameters:
1205f6dfbefdSBarry Smith + snes    - the `SNES` context
1206d25893d9SBarry Smith . compute - function to compute the context
120749abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence
1208d25893d9SBarry Smith 
1209420bcc1bSBarry Smith   Calling sequence of `compute`:
1210420bcc1bSBarry Smith + snes - the `SNES` context
1211420bcc1bSBarry Smith - ctx  - context to be computed
1212420bcc1bSBarry Smith 
1213d25893d9SBarry Smith   Level: intermediate
1214d25893d9SBarry Smith 
1215f6dfbefdSBarry Smith   Note:
1216f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1217f6dfbefdSBarry Smith 
1218f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1219f6dfbefdSBarry Smith 
122049abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn`
1221d25893d9SBarry Smith @*/
122249abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy)
1223d71ae5a4SJacob Faibussowitsch {
1224d25893d9SBarry Smith   PetscFunctionBegin;
1225d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1226d25893d9SBarry Smith   snes->ops->usercompute = compute;
122749abdd8aSBarry Smith   snes->ops->ctxdestroy  = destroy;
12283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1229d25893d9SBarry Smith }
1230a847f771SSatish Balay 
1231b07ff414SBarry Smith /*@
1232f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12339b94acceSBarry Smith 
1234c3339decSBarry Smith   Logically Collective
1235fee21e36SBarry Smith 
1236c7afd0dbSLois Curfman McInnes   Input Parameters:
1237f6dfbefdSBarry Smith + snes - the `SNES` context
1238ce78bad3SBarry Smith - ctx  - the user context
1239c7afd0dbSLois Curfman McInnes 
124036851e7fSLois Curfman McInnes   Level: intermediate
124136851e7fSLois Curfman McInnes 
1242f6dfbefdSBarry Smith   Notes:
1243ce78bad3SBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function
1244f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1245f6dfbefdSBarry Smith 
1246f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1247f6dfbefdSBarry Smith 
1248420bcc1bSBarry Smith   Fortran Note:
1249ce78bad3SBarry Smith   This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
1250ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for
1251ce78bad3SBarry Smith   an example.
1252daf670e6SBarry Smith 
12531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12549b94acceSBarry Smith @*/
125549abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx)
1256d71ae5a4SJacob Faibussowitsch {
1257b07ff414SBarry Smith   KSP ksp;
12581b2093e4SBarry Smith 
12593a40ed3dSBarry Smith   PetscFunctionBegin;
12600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12619566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
126249abdd8aSBarry Smith   PetscCall(KSPSetApplicationContext(ksp, ctx));
126349abdd8aSBarry Smith   snes->ctx = ctx;
12643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12659b94acceSBarry Smith }
126674679c65SBarry Smith 
1267b07ff414SBarry Smith /*@
12689b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1269420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12709b94acceSBarry Smith 
1271c7afd0dbSLois Curfman McInnes   Not Collective
1272c7afd0dbSLois Curfman McInnes 
12739b94acceSBarry Smith   Input Parameter:
1274f6dfbefdSBarry Smith . snes - `SNES` context
12759b94acceSBarry Smith 
12769b94acceSBarry Smith   Output Parameter:
127749abdd8aSBarry Smith . ctx - user context
12789b94acceSBarry Smith 
127936851e7fSLois Curfman McInnes   Level: intermediate
128036851e7fSLois Curfman McInnes 
1281ce78bad3SBarry Smith   Fortran Notes:
1282ce78bad3SBarry Smith   This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this
1283ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
1284ce78bad3SBarry Smith .vb
1285ce78bad3SBarry Smith   Interface SNESGetApplicationContext
1286ce78bad3SBarry Smith     Subroutine SNESGetApplicationContext(snes,ctx,ierr)
1287ce78bad3SBarry Smith   #include <petsc/finclude/petscsnes.h>
1288ce78bad3SBarry Smith       use petscsnes
1289ce78bad3SBarry Smith       SNES snes
1290ce78bad3SBarry Smith       type(tUsertype), pointer :: ctx
1291ce78bad3SBarry Smith       PetscErrorCode ierr
1292ce78bad3SBarry Smith     End Subroutine
1293ce78bad3SBarry Smith   End Interface SNESGetApplicationContext
1294ce78bad3SBarry Smith .ve
1295ce78bad3SBarry Smith 
1296bfe80ac4SPierre Jolivet   The prototype for `ctx` must be
1297ce78bad3SBarry Smith .vb
1298ce78bad3SBarry Smith   type(tUsertype), pointer :: ctx
1299ce78bad3SBarry Smith .ve
1300dc4c0fb0SBarry Smith 
1301420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13029b94acceSBarry Smith @*/
1303ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx)
1304d71ae5a4SJacob Faibussowitsch {
13053a40ed3dSBarry Smith   PetscFunctionBegin;
13060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
130749abdd8aSBarry Smith   *(void **)ctx = snes->ctx;
13083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13099b94acceSBarry Smith }
131074679c65SBarry Smith 
13119b94acceSBarry Smith /*@
1312420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13133565c898SBarry Smith 
1314dc4c0fb0SBarry Smith   Logically Collective
13153565c898SBarry Smith 
13163565c898SBarry Smith   Input Parameters:
1317f6dfbefdSBarry Smith + snes        - `SNES` context
1318f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1319f6dfbefdSBarry 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
1320420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13213565c898SBarry Smith 
1322f6dfbefdSBarry Smith   Options Database Keys:
132301c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1324f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1325ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1326ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13273565c898SBarry Smith 
13283565c898SBarry Smith   Level: intermediate
13293565c898SBarry Smith 
1330f6dfbefdSBarry Smith   Note:
1331420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1332420bcc1bSBarry Smith   and computing explicitly with
1333f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1334ec5066bdSBarry Smith 
1335420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13363565c898SBarry Smith @*/
1337d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1338d71ae5a4SJacob Faibussowitsch {
13393565c898SBarry Smith   PetscFunctionBegin;
13403565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
134188b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
134288b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13434ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13443565c898SBarry Smith   snes->mf_operator = mf_operator;
13453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13463565c898SBarry Smith }
13473565c898SBarry Smith 
13483565c898SBarry Smith /*@
1349dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13503565c898SBarry Smith 
1351420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13523565c898SBarry Smith 
13533565c898SBarry Smith   Input Parameter:
1354f6dfbefdSBarry Smith . snes - `SNES` context
13553565c898SBarry Smith 
13563565c898SBarry Smith   Output Parameters:
1357f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1358f6dfbefdSBarry 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
13593565c898SBarry Smith 
13603565c898SBarry Smith   Level: intermediate
13613565c898SBarry Smith 
13621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13633565c898SBarry Smith @*/
1364d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1365d71ae5a4SJacob Faibussowitsch {
13663565c898SBarry Smith   PetscFunctionBegin;
13673565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13683565c898SBarry Smith   if (mf) *mf = snes->mf;
13693565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13713565c898SBarry Smith }
13723565c898SBarry Smith 
13733565c898SBarry Smith /*@
1374420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13759b94acceSBarry Smith 
1376c7afd0dbSLois Curfman McInnes   Not Collective
1377c7afd0dbSLois Curfman McInnes 
13789b94acceSBarry Smith   Input Parameter:
1379f6dfbefdSBarry Smith . snes - `SNES` context
13809b94acceSBarry Smith 
13819b94acceSBarry Smith   Output Parameter:
13829b94acceSBarry Smith . iter - iteration number
13839b94acceSBarry Smith 
1384dc4c0fb0SBarry Smith   Level: intermediate
1385dc4c0fb0SBarry Smith 
1386c8228a4eSBarry Smith   Notes:
1387c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1388c8228a4eSBarry Smith 
1389c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1390f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
139108405cd6SLois Curfman McInnes .vb
139208405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
139308405cd6SLois Curfman McInnes       if (!(it % 2)) {
139408405cd6SLois Curfman McInnes         [compute Jacobian here]
139508405cd6SLois Curfman McInnes       }
139608405cd6SLois Curfman McInnes .ve
1397f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1398f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1399c8228a4eSBarry Smith 
1400f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1401c04deec6SBarry Smith 
1402420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14039b94acceSBarry Smith @*/
1404d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1405d71ae5a4SJacob Faibussowitsch {
14063a40ed3dSBarry Smith   PetscFunctionBegin;
14070700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14084f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14099b94acceSBarry Smith   *iter = snes->iter;
14103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14119b94acceSBarry Smith }
141274679c65SBarry Smith 
1413360c497dSPeter Brune /*@
1414360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1415360c497dSPeter Brune 
1416360c497dSPeter Brune   Not Collective
1417360c497dSPeter Brune 
1418d8d19677SJose E. Roman   Input Parameters:
1419f6dfbefdSBarry Smith + snes - `SNES` context
1420a2b725a8SWilliam Gropp - iter - iteration number
1421360c497dSPeter Brune 
1422360c497dSPeter Brune   Level: developer
1423360c497dSPeter Brune 
1424420bcc1bSBarry Smith   Note:
1425420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1426420bcc1bSBarry Smith 
14271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1428360c497dSPeter Brune @*/
1429d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1430d71ae5a4SJacob Faibussowitsch {
1431360c497dSPeter Brune   PetscFunctionBegin;
1432360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1434360c497dSPeter Brune   snes->iter = iter;
14359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1437360c497dSPeter Brune }
1438360c497dSPeter Brune 
14399b94acceSBarry Smith /*@
1440b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1441420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14429b94acceSBarry Smith 
1443c7afd0dbSLois Curfman McInnes   Not Collective
1444c7afd0dbSLois Curfman McInnes 
14459b94acceSBarry Smith   Input Parameter:
1446f6dfbefdSBarry Smith . snes - `SNES` context
14479b94acceSBarry Smith 
14489b94acceSBarry Smith   Output Parameter:
14499b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14509b94acceSBarry Smith 
1451dc4c0fb0SBarry Smith   Level: intermediate
1452dc4c0fb0SBarry Smith 
1453f6dfbefdSBarry Smith   Note:
1454f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1455c96a6f78SLois Curfman McInnes 
14561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1457db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14589b94acceSBarry Smith @*/
1459d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1460d71ae5a4SJacob Faibussowitsch {
14613a40ed3dSBarry Smith   PetscFunctionBegin;
14620700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14634f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
146450ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
146650ffb88aSMatthew Knepley }
146750ffb88aSMatthew Knepley 
146850ffb88aSMatthew Knepley /*@
1469b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1470420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
147150ffb88aSMatthew Knepley 
147250ffb88aSMatthew Knepley   Not Collective
147350ffb88aSMatthew Knepley 
147450ffb88aSMatthew Knepley   Input Parameters:
1475f6dfbefdSBarry Smith + snes     - `SNES` context
147677e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
147750ffb88aSMatthew Knepley 
1478420bcc1bSBarry Smith   Options Database Key:
1479420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1480420bcc1bSBarry Smith 
148150ffb88aSMatthew Knepley   Level: intermediate
148250ffb88aSMatthew Knepley 
1483420bcc1bSBarry Smith   Developer Note:
1484420bcc1bSBarry Smith   The options database key is wrong for this function name
1485420bcc1bSBarry Smith 
14861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1487db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
148850ffb88aSMatthew Knepley @*/
1489d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1490d71ae5a4SJacob Faibussowitsch {
149150ffb88aSMatthew Knepley   PetscFunctionBegin;
14920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
149377e5a1f9SBarry Smith 
149477e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
14951690c2aeSBarry Smith     snes->maxFailures = PETSC_INT_MAX;
149677e5a1f9SBarry Smith   } else {
149777e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
149850ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
149977e5a1f9SBarry Smith   }
15003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
150150ffb88aSMatthew Knepley }
150250ffb88aSMatthew Knepley 
150350ffb88aSMatthew Knepley /*@
1504b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1505420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
150650ffb88aSMatthew Knepley 
150750ffb88aSMatthew Knepley   Not Collective
150850ffb88aSMatthew Knepley 
150950ffb88aSMatthew Knepley   Input Parameter:
151020f4b53cSBarry Smith . snes - `SNES` context
151150ffb88aSMatthew Knepley 
151250ffb88aSMatthew Knepley   Output Parameter:
151350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
151450ffb88aSMatthew Knepley 
151550ffb88aSMatthew Knepley   Level: intermediate
151650ffb88aSMatthew Knepley 
15171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1518db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
151950ffb88aSMatthew Knepley @*/
1520d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1521d71ae5a4SJacob Faibussowitsch {
152250ffb88aSMatthew Knepley   PetscFunctionBegin;
15230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15244f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
152550ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15279b94acceSBarry Smith }
1528a847f771SSatish Balay 
15292541af92SBarry Smith /*@
15302541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1531420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15322541af92SBarry Smith 
15332541af92SBarry Smith   Not Collective
15342541af92SBarry Smith 
15352541af92SBarry Smith   Input Parameter:
1536f6dfbefdSBarry Smith . snes - `SNES` context
15372541af92SBarry Smith 
15382541af92SBarry Smith   Output Parameter:
15392541af92SBarry Smith . nfuncs - number of evaluations
15402541af92SBarry Smith 
15412541af92SBarry Smith   Level: intermediate
15422541af92SBarry Smith 
1543f6dfbefdSBarry Smith   Note:
1544f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1545971e163fSPeter Brune 
15461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15472541af92SBarry Smith @*/
1548d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1549d71ae5a4SJacob Faibussowitsch {
15502541af92SBarry Smith   PetscFunctionBegin;
15510700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15524f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15532541af92SBarry Smith   *nfuncs = snes->nfuncs;
15543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15552541af92SBarry Smith }
15562541af92SBarry Smith 
15573d4c4710SBarry Smith /*@
15583d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1559420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15603d4c4710SBarry Smith 
15613d4c4710SBarry Smith   Not Collective
15623d4c4710SBarry Smith 
15633d4c4710SBarry Smith   Input Parameter:
1564f6dfbefdSBarry Smith . snes - `SNES` context
15653d4c4710SBarry Smith 
15663d4c4710SBarry Smith   Output Parameter:
15673d4c4710SBarry Smith . nfails - number of failed solves
15683d4c4710SBarry Smith 
1569f6dfbefdSBarry Smith   Options Database Key:
15709d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15719d85da0cSMatthew G. Knepley 
1572f6dfbefdSBarry Smith   Level: intermediate
1573f6dfbefdSBarry Smith 
1574f6dfbefdSBarry Smith   Note:
1575f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15763d4c4710SBarry Smith 
15771cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15783d4c4710SBarry Smith @*/
1579d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1580d71ae5a4SJacob Faibussowitsch {
15813d4c4710SBarry Smith   PetscFunctionBegin;
15820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15834f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15843d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15863d4c4710SBarry Smith }
15873d4c4710SBarry Smith 
15883d4c4710SBarry Smith /*@
15893d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1590f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15913d4c4710SBarry Smith 
1592c3339decSBarry Smith   Logically Collective
15933d4c4710SBarry Smith 
15943d4c4710SBarry Smith   Input Parameters:
1595f6dfbefdSBarry Smith + snes     - `SNES` context
159677e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
15973d4c4710SBarry Smith 
1598f6dfbefdSBarry Smith   Options Database Key:
15999d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16009d85da0cSMatthew G. Knepley 
1601dc4c0fb0SBarry Smith   Level: intermediate
1602dc4c0fb0SBarry Smith 
1603f6dfbefdSBarry Smith   Note:
1604f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16053d4c4710SBarry Smith 
1606420bcc1bSBarry Smith   Developer Note:
1607420bcc1bSBarry Smith   The options database key is wrong for this function name
1608420bcc1bSBarry Smith 
16091cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16103d4c4710SBarry Smith @*/
1611d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1612d71ae5a4SJacob Faibussowitsch {
16133d4c4710SBarry Smith   PetscFunctionBegin;
16140700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1615c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
161677e5a1f9SBarry Smith 
161777e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
16181690c2aeSBarry Smith     snes->maxLinearSolveFailures = PETSC_INT_MAX;
161977e5a1f9SBarry Smith   } else {
162077e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16213d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
162277e5a1f9SBarry Smith   }
16233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16243d4c4710SBarry Smith }
16253d4c4710SBarry Smith 
16263d4c4710SBarry Smith /*@
16273d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1628f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16293d4c4710SBarry Smith 
16303d4c4710SBarry Smith   Not Collective
16313d4c4710SBarry Smith 
16323d4c4710SBarry Smith   Input Parameter:
1633f6dfbefdSBarry Smith . snes - `SNES` context
16343d4c4710SBarry Smith 
16353d4c4710SBarry Smith   Output Parameter:
16363d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16373d4c4710SBarry Smith 
16383d4c4710SBarry Smith   Level: intermediate
16393d4c4710SBarry Smith 
1640f6dfbefdSBarry Smith   Note:
1641f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16423d4c4710SBarry Smith 
16431cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16443d4c4710SBarry Smith @*/
1645d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1646d71ae5a4SJacob Faibussowitsch {
16473d4c4710SBarry Smith   PetscFunctionBegin;
16480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16494f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16503d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16523d4c4710SBarry Smith }
16533d4c4710SBarry Smith 
1654c96a6f78SLois Curfman McInnes /*@
1655b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1656420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1657c96a6f78SLois Curfman McInnes 
1658c7afd0dbSLois Curfman McInnes   Not Collective
1659c7afd0dbSLois Curfman McInnes 
1660c96a6f78SLois Curfman McInnes   Input Parameter:
1661f6dfbefdSBarry Smith . snes - `SNES` context
1662c96a6f78SLois Curfman McInnes 
1663c96a6f78SLois Curfman McInnes   Output Parameter:
1664c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1665c96a6f78SLois Curfman McInnes 
1666dc4c0fb0SBarry Smith   Level: intermediate
1667dc4c0fb0SBarry Smith 
1668c96a6f78SLois Curfman McInnes   Notes:
1669f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1670c96a6f78SLois Curfman McInnes 
1671f6dfbefdSBarry 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
1672f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1673010be392SBarry Smith 
16741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1675c96a6f78SLois Curfman McInnes @*/
1676d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1677d71ae5a4SJacob Faibussowitsch {
16783a40ed3dSBarry Smith   PetscFunctionBegin;
16790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16804f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1681c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1683c96a6f78SLois Curfman McInnes }
1684c96a6f78SLois Curfman McInnes 
1685971e163fSPeter Brune /*@
1686971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1687f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1688971e163fSPeter Brune 
1689c3339decSBarry Smith   Logically Collective
1690971e163fSPeter Brune 
1691d8d19677SJose E. Roman   Input Parameters:
1692f6dfbefdSBarry Smith + snes  - `SNES` context
1693f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1694971e163fSPeter Brune 
1695971e163fSPeter Brune   Level: developer
1696971e163fSPeter Brune 
16971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1698971e163fSPeter Brune @*/
1699d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1700d71ae5a4SJacob Faibussowitsch {
1701971e163fSPeter Brune   PetscFunctionBegin;
1702971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1703971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1704971e163fSPeter Brune   snes->counters_reset = reset;
17053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1706971e163fSPeter Brune }
1707971e163fSPeter Brune 
17082999313aSBarry Smith /*@
170912b1dd1aSStefano Zampini   SNESResetCounters - Reset counters for linear iterations and function evaluations.
171012b1dd1aSStefano Zampini 
171112b1dd1aSStefano Zampini   Logically Collective
171212b1dd1aSStefano Zampini 
171312b1dd1aSStefano Zampini   Input Parameters:
171412b1dd1aSStefano Zampini . snes - `SNES` context
171512b1dd1aSStefano Zampini 
171612b1dd1aSStefano Zampini   Level: developer
171712b1dd1aSStefano Zampini 
171812b1dd1aSStefano Zampini   Note:
171912b1dd1aSStefano Zampini   It honors the flag set with `SNESSetCountersReset()`
172012b1dd1aSStefano Zampini 
172112b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
172212b1dd1aSStefano Zampini @*/
172312b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
172412b1dd1aSStefano Zampini {
172512b1dd1aSStefano Zampini   PetscFunctionBegin;
172612b1dd1aSStefano Zampini   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
172712b1dd1aSStefano Zampini   if (snes->counters_reset) {
172812b1dd1aSStefano Zampini     snes->nfuncs      = 0;
172912b1dd1aSStefano Zampini     snes->linear_its  = 0;
173012b1dd1aSStefano Zampini     snes->numFailures = 0;
173112b1dd1aSStefano Zampini   }
173212b1dd1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
173312b1dd1aSStefano Zampini }
173412b1dd1aSStefano Zampini 
173512b1dd1aSStefano Zampini /*@
1736f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17372999313aSBarry Smith 
1738420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17392999313aSBarry Smith 
17402999313aSBarry Smith   Input Parameters:
1741f6dfbefdSBarry Smith + snes - the `SNES` context
1742f6dfbefdSBarry Smith - ksp  - the `KSP` context
17432999313aSBarry Smith 
1744dc4c0fb0SBarry Smith   Level: developer
1745dc4c0fb0SBarry Smith 
17462999313aSBarry Smith   Notes:
1747f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17482999313aSBarry Smith   so this routine is rarely needed.
17492999313aSBarry Smith 
1750f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1751420bcc1bSBarry Smith   decreased by one when this is called.
17522999313aSBarry Smith 
175342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17542999313aSBarry Smith @*/
1755d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1756d71ae5a4SJacob Faibussowitsch {
17572999313aSBarry Smith   PetscFunctionBegin;
17580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17590700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17602999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17619566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17629566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17632999313aSBarry Smith   snes->ksp = ksp;
17643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17652999313aSBarry Smith }
17662999313aSBarry Smith 
176752baeb72SSatish Balay /*@
176877e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
176977e5a1f9SBarry Smith   currently contain default values
177077e5a1f9SBarry Smith 
177177e5a1f9SBarry Smith   Collective
177277e5a1f9SBarry Smith 
177377e5a1f9SBarry Smith   Input Parameter:
177477e5a1f9SBarry Smith . snes - the `SNES` object
177577e5a1f9SBarry Smith 
177677e5a1f9SBarry Smith   Level: developer
177777e5a1f9SBarry Smith 
177877e5a1f9SBarry Smith   Developer Note:
177977e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
178077e5a1f9SBarry Smith 
178177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
178277e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
178377e5a1f9SBarry Smith @*/
178477e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
178577e5a1f9SBarry Smith {
178677e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
178777e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
178877e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
178977e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
179077e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
179177e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
179277e5a1f9SBarry Smith   return PETSC_SUCCESS;
179377e5a1f9SBarry Smith }
179477e5a1f9SBarry Smith 
179577e5a1f9SBarry Smith /*@
1796dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
17979b94acceSBarry Smith 
1798d083f849SBarry Smith   Collective
1799c7afd0dbSLois Curfman McInnes 
1800f6dfbefdSBarry Smith   Input Parameter:
1801906ed7ccSBarry Smith . comm - MPI communicator
18029b94acceSBarry Smith 
18039b94acceSBarry Smith   Output Parameter:
180420f4b53cSBarry Smith . outsnes - the new `SNES` context
18059b94acceSBarry Smith 
1806c7afd0dbSLois Curfman McInnes   Options Database Keys:
18077addb90fSBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner
18087addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()`
1809dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1810c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1811c1f60f51SBarry Smith 
181236851e7fSLois Curfman McInnes   Level: beginner
181336851e7fSLois Curfman McInnes 
181495452b02SPatrick Sanan   Developer Notes:
1815f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1816efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1817f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1818f6dfbefdSBarry Smith   in `SNESView()`.
1819efd4aadfSBarry Smith 
1820f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1821f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1822f6dfbefdSBarry Smith 
18237addb90fSBarry Smith   `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed.
1824efd4aadfSBarry Smith 
1825e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18269b94acceSBarry Smith @*/
1827d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1828d71ae5a4SJacob Faibussowitsch {
18299b94acceSBarry Smith   SNES       snes;
1830fa9f3622SBarry Smith   SNESKSPEW *kctx;
183137fcc0dbSBarry Smith 
18323a40ed3dSBarry Smith   PetscFunctionBegin;
18334f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18349566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18358ba1e511SMatthew Knepley 
18369566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18378d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18382c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18399b94acceSBarry Smith   snes->norm           = 0.0;
1840c1e67a49SFande Kong   snes->xnorm          = 0.0;
1841c1e67a49SFande Kong   snes->ynorm          = 0.0;
1842365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18436c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1844b4874afaSBarry Smith   snes->ttol           = 0.0;
184577e5a1f9SBarry Smith 
1846e37c518bSBarry Smith   snes->rnorm0               = 0;
18479b94acceSBarry Smith   snes->nfuncs               = 0;
184850ffb88aSMatthew Knepley   snes->numFailures          = 0;
184950ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18507a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1851e35cf81dSBarry Smith   snes->lagjacobian          = 1;
185237ec4e1aSPeter Brune   snes->jac_iter             = 0;
185337ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1854a8054027SBarry Smith   snes->lagpreconditioner    = 1;
185537ec4e1aSPeter Brune   snes->pre_iter             = 0;
185637ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1857639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1858c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18599e5d0892SLisandro Dalcin   snes->data                 = NULL;
18604dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1861186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18626f24a144SLois Curfman McInnes   snes->nwork                = 0;
18639e5d0892SLisandro Dalcin   snes->work                 = NULL;
186458c9b817SLisandro Dalcin   snes->nvwork               = 0;
18659e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1866758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1867758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18680298fd71SBarry Smith   snes->conv_hist            = NULL;
18690298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1870758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1871971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1872e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1873184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1874efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1875b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1876c40d0f55SPeter Brune 
1877d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1878d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1879d8f46077SPeter Brune   snes->mf_version  = 1;
1880d8f46077SPeter Brune 
18813d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18823d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18833d4c4710SBarry Smith 
1884349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
188576bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1886349187a7SBarry Smith 
18874fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18884fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
18894fc747eaSLawrence Mitchell 
18909b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18914dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1892f5af7f23SKarl Rupp 
1893835f2295SStefano Zampini   snes->kspconvctx  = kctx;
18949b94acceSBarry Smith   kctx->version     = 2;
18950f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
18969b94acceSBarry Smith                              this was too large for some test cases */
189775567043SBarry Smith   kctx->rtol_last   = 0.0;
18980f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
18999b94acceSBarry Smith   kctx->gamma       = 1.0;
19000f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
190171f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
19020f0abf79SStefano Zampini   kctx->threshold   = 0.1;
190375567043SBarry Smith   kctx->lresid_last = 0.0;
190475567043SBarry Smith   kctx->norm_last   = 0.0;
19059b94acceSBarry Smith 
19060f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
19070f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
19080f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
19090f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
19100f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19110f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19120f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19130f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19140f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19150f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19160f0abf79SStefano Zampini 
1917b50c806fSBarry Smith   PetscCall(SNESParametersInitialize(snes));
19189b94acceSBarry Smith   *outsnes = snes;
19193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19209b94acceSBarry Smith }
19219b94acceSBarry Smith 
19229b94acceSBarry Smith /*@C
19239b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1924f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19259b94acceSBarry Smith   equations.
19269b94acceSBarry Smith 
1927c3339decSBarry Smith   Logically Collective
1928fee21e36SBarry Smith 
1929c7afd0dbSLois Curfman McInnes   Input Parameters:
1930f6dfbefdSBarry Smith + snes - the `SNES` context
1931dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19328434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1933c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1934dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19359b94acceSBarry Smith 
193636851e7fSLois Curfman McInnes   Level: beginner
193736851e7fSLois Curfman McInnes 
19388434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19399b94acceSBarry Smith @*/
19408434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1941d71ae5a4SJacob Faibussowitsch {
19426cab3a1bSJed Brown   DM dm;
19436cab3a1bSJed Brown 
19443a40ed3dSBarry Smith   PetscFunctionBegin;
19450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1946d2a683ecSLisandro Dalcin   if (r) {
1947d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1948d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19499566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19509566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
195185385478SLisandro Dalcin     snes->vec_func = r;
1952d2a683ecSLisandro Dalcin   }
19539566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19549566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
195548a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19579b94acceSBarry Smith }
19589b94acceSBarry Smith 
1959e4ed7901SPeter Brune /*@C
19600b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1961e4ed7901SPeter Brune 
1962c3339decSBarry Smith   Logically Collective
1963e4ed7901SPeter Brune 
1964e4ed7901SPeter Brune   Input Parameters:
1965f6dfbefdSBarry Smith + snes - the `SNES` context
1966e4ed7901SPeter Brune - f    - vector to store function value
1967e4ed7901SPeter Brune 
1968dc4c0fb0SBarry Smith   Level: developer
1969dc4c0fb0SBarry Smith 
1970e4ed7901SPeter Brune   Notes:
1971e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1972e4ed7901SPeter Brune 
1973f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1974e4ed7901SPeter Brune 
19751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1976e4ed7901SPeter Brune @*/
1977d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1978d71ae5a4SJacob Faibussowitsch {
1979e4ed7901SPeter Brune   Vec vec_func;
1980e4ed7901SPeter Brune 
1981e4ed7901SPeter Brune   PetscFunctionBegin;
1982e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1983e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1984e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1985efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1986902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19873ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1988902f982fSPeter Brune   }
19899566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19909566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1991f5af7f23SKarl Rupp 
1992217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1994e4ed7901SPeter Brune }
1995e4ed7901SPeter Brune 
1996534ebe21SPeter Brune /*@
1997f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1998f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1999534ebe21SPeter Brune 
2000c3339decSBarry Smith   Logically Collective
2001534ebe21SPeter Brune 
2002534ebe21SPeter Brune   Input Parameters:
2003f6dfbefdSBarry Smith + snes         - the `SNES` context
2004365a6726SPeter Brune - normschedule - the frequency of norm computation
2005534ebe21SPeter Brune 
2006517f1916SMatthew G. Knepley   Options Database Key:
200767b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2008517f1916SMatthew G. Knepley 
2009dc4c0fb0SBarry Smith   Level: advanced
2010dc4c0fb0SBarry Smith 
2011534ebe21SPeter Brune   Notes:
2012f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2013534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2014534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2015f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2016534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2017534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2018534ebe21SPeter Brune   their solution.
2019534ebe21SPeter Brune 
2020e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2021534ebe21SPeter Brune @*/
2022d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2023d71ae5a4SJacob Faibussowitsch {
2024534ebe21SPeter Brune   PetscFunctionBegin;
2025534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2026365a6726SPeter Brune   snes->normschedule = normschedule;
20273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2028534ebe21SPeter Brune }
2029534ebe21SPeter Brune 
2030534ebe21SPeter Brune /*@
2031f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2032f6dfbefdSBarry Smith   of the `SNES` method.
2033534ebe21SPeter Brune 
2034c3339decSBarry Smith   Logically Collective
2035534ebe21SPeter Brune 
2036534ebe21SPeter Brune   Input Parameters:
2037f6dfbefdSBarry Smith + snes         - the `SNES` context
2038365a6726SPeter Brune - normschedule - the type of the norm used
2039534ebe21SPeter Brune 
2040534ebe21SPeter Brune   Level: advanced
2041534ebe21SPeter Brune 
20421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2043534ebe21SPeter Brune @*/
2044d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2045d71ae5a4SJacob Faibussowitsch {
2046534ebe21SPeter Brune   PetscFunctionBegin;
2047534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2048365a6726SPeter Brune   *normschedule = snes->normschedule;
20493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2050534ebe21SPeter Brune }
2051534ebe21SPeter Brune 
2052c5ce4427SMatthew G. Knepley /*@
2053c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2054c5ce4427SMatthew G. Knepley 
2055c3339decSBarry Smith   Logically Collective
2056c5ce4427SMatthew G. Knepley 
2057c5ce4427SMatthew G. Knepley   Input Parameters:
2058f6dfbefdSBarry Smith + snes - the `SNES` context
2059f6dfbefdSBarry Smith - norm - the value of the norm
2060c5ce4427SMatthew G. Knepley 
2061c5ce4427SMatthew G. Knepley   Level: developer
2062c5ce4427SMatthew G. Knepley 
20631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2064c5ce4427SMatthew G. Knepley @*/
2065d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2066d71ae5a4SJacob Faibussowitsch {
2067c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2068c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2069c5ce4427SMatthew G. Knepley   snes->norm = norm;
20703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2071c5ce4427SMatthew G. Knepley }
2072c5ce4427SMatthew G. Knepley 
2073c5ce4427SMatthew G. Knepley /*@
2074c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2075c5ce4427SMatthew G. Knepley 
2076c5ce4427SMatthew G. Knepley   Not Collective
2077c5ce4427SMatthew G. Knepley 
2078c5ce4427SMatthew G. Knepley   Input Parameter:
2079f6dfbefdSBarry Smith . snes - the `SNES` context
2080c5ce4427SMatthew G. Knepley 
2081c5ce4427SMatthew G. Knepley   Output Parameter:
2082c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2083c5ce4427SMatthew G. Knepley 
2084c5ce4427SMatthew G. Knepley   Level: developer
2085c5ce4427SMatthew G. Knepley 
20861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2087c5ce4427SMatthew G. Knepley @*/
2088d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2089d71ae5a4SJacob Faibussowitsch {
2090c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2091c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20924f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2093c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2095c5ce4427SMatthew G. Knepley }
2096c5ce4427SMatthew G. Knepley 
2097c1e67a49SFande Kong /*@
2098f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2099c1e67a49SFande Kong 
2100c1e67a49SFande Kong   Not Collective
2101c1e67a49SFande Kong 
2102c1e67a49SFande Kong   Input Parameter:
2103f6dfbefdSBarry Smith . snes - the `SNES` context
2104c1e67a49SFande Kong 
2105c1e67a49SFande Kong   Output Parameter:
2106c1e67a49SFande Kong . ynorm - the last computed update norm
2107c1e67a49SFande Kong 
2108c1e67a49SFande Kong   Level: developer
2109c1e67a49SFande Kong 
2110f6dfbefdSBarry Smith   Note:
2111f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2112f6dfbefdSBarry Smith 
21131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2114c1e67a49SFande Kong @*/
2115d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2116d71ae5a4SJacob Faibussowitsch {
2117c1e67a49SFande Kong   PetscFunctionBegin;
2118c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21194f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2120c1e67a49SFande Kong   *ynorm = snes->ynorm;
21213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2122c1e67a49SFande Kong }
2123c1e67a49SFande Kong 
2124c1e67a49SFande Kong /*@
21254591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2126c1e67a49SFande Kong 
2127c1e67a49SFande Kong   Not Collective
2128c1e67a49SFande Kong 
2129c1e67a49SFande Kong   Input Parameter:
2130f6dfbefdSBarry Smith . snes - the `SNES` context
2131c1e67a49SFande Kong 
2132c1e67a49SFande Kong   Output Parameter:
2133c1e67a49SFande Kong . xnorm - the last computed solution norm
2134c1e67a49SFande Kong 
2135c1e67a49SFande Kong   Level: developer
2136c1e67a49SFande Kong 
21371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2138c1e67a49SFande Kong @*/
2139d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2140d71ae5a4SJacob Faibussowitsch {
2141c1e67a49SFande Kong   PetscFunctionBegin;
2142c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21434f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2144c1e67a49SFande Kong   *xnorm = snes->xnorm;
21453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2146c1e67a49SFande Kong }
2147c1e67a49SFande Kong 
2148cc4c1da9SBarry Smith /*@
2149f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2150f6dfbefdSBarry Smith   of the `SNES` method.
215147073ea2SPeter Brune 
2152c3339decSBarry Smith   Logically Collective
215347073ea2SPeter Brune 
215447073ea2SPeter Brune   Input Parameters:
2155f6dfbefdSBarry Smith + snes - the `SNES` context
2156f6dfbefdSBarry Smith - type - the function type
215747073ea2SPeter Brune 
215847073ea2SPeter Brune   Level: developer
215947073ea2SPeter Brune 
2160420bcc1bSBarry Smith   Values of the function type\:
2161f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2162f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2163f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2164f6dfbefdSBarry Smith 
2165420bcc1bSBarry Smith   Note:
2166f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2167f6dfbefdSBarry Smith 
21681cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
216947073ea2SPeter Brune @*/
2170d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2171d71ae5a4SJacob Faibussowitsch {
217247073ea2SPeter Brune   PetscFunctionBegin;
217347073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
217447073ea2SPeter Brune   snes->functype = type;
21753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
217647073ea2SPeter Brune }
217747073ea2SPeter Brune 
2178cc4c1da9SBarry Smith /*@
2179f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
218047073ea2SPeter Brune   of the SNES method.
218147073ea2SPeter Brune 
2182c3339decSBarry Smith   Logically Collective
218347073ea2SPeter Brune 
218447073ea2SPeter Brune   Input Parameters:
2185f6dfbefdSBarry Smith + snes - the `SNES` context
2186f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
218747073ea2SPeter Brune 
218847073ea2SPeter Brune   Level: advanced
218947073ea2SPeter Brune 
21901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
219147073ea2SPeter Brune @*/
2192d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2193d71ae5a4SJacob Faibussowitsch {
219447073ea2SPeter Brune   PetscFunctionBegin;
219547073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
219647073ea2SPeter Brune   *type = snes->functype;
21973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2198534ebe21SPeter Brune }
2199534ebe21SPeter Brune 
2200c79ef259SPeter Brune /*@C
2201be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2202c79ef259SPeter Brune   use with composed nonlinear solvers.
2203c79ef259SPeter Brune 
2204c79ef259SPeter Brune   Input Parameters:
22059bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22068434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
220777e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2208c79ef259SPeter Brune 
2209dc4c0fb0SBarry Smith   Level: intermediate
2210dc4c0fb0SBarry Smith 
2211f6dfbefdSBarry Smith   Note:
2212f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2213f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2214c79ef259SPeter Brune 
22158434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2216c79ef259SPeter Brune @*/
22178434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2218d71ae5a4SJacob Faibussowitsch {
22196cab3a1bSJed Brown   DM dm;
22206cab3a1bSJed Brown 
2221646217ecSPeter Brune   PetscFunctionBegin;
22226cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22239566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22249566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2226646217ecSPeter Brune }
2227646217ecSPeter Brune 
2228bbc1464cSBarry Smith /*
2229bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2230bbc1464cSBarry Smith    changed during the KSPSolve()
2231bbc1464cSBarry Smith */
2232d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2233d71ae5a4SJacob Faibussowitsch {
2234bbc1464cSBarry Smith   DM     dm;
2235bbc1464cSBarry Smith   DMSNES sdm;
2236bbc1464cSBarry Smith 
2237bbc1464cSBarry Smith   PetscFunctionBegin;
22389566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22399566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2240bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2241bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2242792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22439566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22440df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2245ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2246792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22479566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2248bbc1464cSBarry Smith   } else {
2249792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22509566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2251bbc1464cSBarry Smith   }
22523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2253bbc1464cSBarry Smith }
2254bbc1464cSBarry Smith 
2255d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2256d71ae5a4SJacob Faibussowitsch {
2257e03ab78fSPeter Brune   DM     dm;
2258942e3340SBarry Smith   DMSNES sdm;
22596cab3a1bSJed Brown 
22608b0a5094SBarry Smith   PetscFunctionBegin;
22619566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22629566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22638b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2264bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2265792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22669566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2267792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22689566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2269bbc1464cSBarry Smith   } else {
2270792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22719566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2272bbc1464cSBarry Smith   }
22733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22748b0a5094SBarry Smith }
22758b0a5094SBarry Smith 
2276d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2277d71ae5a4SJacob Faibussowitsch {
22788b0a5094SBarry Smith   PetscFunctionBegin;
2279e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2280bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22819566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22829566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22848b0a5094SBarry Smith }
22858b0a5094SBarry Smith 
22868b0a5094SBarry Smith /*@C
22871d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22888b0a5094SBarry Smith 
2289c3339decSBarry Smith   Logically Collective
22908b0a5094SBarry Smith 
22918b0a5094SBarry Smith   Input Parameters:
2292f6dfbefdSBarry Smith + snes - the `SNES` context
2293dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
22948434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
229526a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed
2296dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
22978434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2298dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2299dc4c0fb0SBarry Smith 
2300dc4c0fb0SBarry Smith   Level: intermediate
23018b0a5094SBarry Smith 
23028b0a5094SBarry Smith   Notes:
230326a11704SBarry Smith   It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use
2304f450aa47SBarry 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.
2305f450aa47SBarry Smith 
2306f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23078b0a5094SBarry Smith 
23081d27aa22SBarry 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}$.
23091d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23108b0a5094SBarry Smith 
231126a11704SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner.
23128b0a5094SBarry Smith 
23130d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23141d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23158b0a5094SBarry Smith 
23168b0a5094SBarry 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
23171d27aa22SBarry 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
23181d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23198b0a5094SBarry Smith 
23201d27aa22SBarry 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
232126a11704SBarry Smith   $A(x^{n})$ is used to build the preconditioner
23226b7fb656SBarry Smith 
232315229ffcSPierre 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.
23246b7fb656SBarry Smith 
2325dc4c0fb0SBarry 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
232626a11704SBarry 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
232726a11704SBarry 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`.
2328aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2329bbc1464cSBarry Smith 
23309bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23318434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23328b0a5094SBarry Smith @*/
23338434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2334d71ae5a4SJacob Faibussowitsch {
2335e03ab78fSPeter Brune   DM dm;
2336e03ab78fSPeter Brune 
23378b0a5094SBarry Smith   PetscFunctionBegin;
23388b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23399566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23409566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23419566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23429566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23439566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23458b0a5094SBarry Smith }
23468b0a5094SBarry Smith 
23477971a8bfSPeter Brune /*@C
23487971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23497971a8bfSPeter Brune 
2350f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23517971a8bfSPeter Brune 
23527971a8bfSPeter Brune   Input Parameter:
2353f6dfbefdSBarry Smith . snes - the `SNES` context
23547971a8bfSPeter Brune 
2355d8d19677SJose E. Roman   Output Parameters:
2356dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23578434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2358dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2359dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23608434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2361dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23627971a8bfSPeter Brune 
23637971a8bfSPeter Brune   Level: advanced
23647971a8bfSPeter Brune 
23658434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23667971a8bfSPeter Brune @*/
23678434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2368d71ae5a4SJacob Faibussowitsch {
23697971a8bfSPeter Brune   DM dm;
23707971a8bfSPeter Brune 
23717971a8bfSPeter Brune   PetscFunctionBegin;
23727971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23739566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23749566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23759566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23769566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23787971a8bfSPeter Brune }
23797971a8bfSPeter Brune 
2380d25893d9SBarry Smith /*@C
2381dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2382d25893d9SBarry Smith 
2383c3339decSBarry Smith   Logically Collective
2384d25893d9SBarry Smith 
2385d25893d9SBarry Smith   Input Parameters:
2386f6dfbefdSBarry Smith + snes - the `SNES` context
23878434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2388d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2389dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2390d25893d9SBarry Smith 
2391d25893d9SBarry Smith   Level: intermediate
2392d25893d9SBarry Smith 
23938434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2394d25893d9SBarry Smith @*/
23958434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2396d71ae5a4SJacob Faibussowitsch {
2397d25893d9SBarry Smith   PetscFunctionBegin;
2398d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2399d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2400d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
24013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2402d25893d9SBarry Smith }
2403d25893d9SBarry Smith 
24041096aae1SMatthew Knepley /*@C
2405dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2406dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
24071096aae1SMatthew Knepley 
2408c3339decSBarry Smith   Logically Collective
24091096aae1SMatthew Knepley 
24101096aae1SMatthew Knepley   Input Parameter:
2411f6dfbefdSBarry Smith . snes - the `SNES` context
24121096aae1SMatthew Knepley 
24131096aae1SMatthew Knepley   Output Parameter:
2414dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24151096aae1SMatthew Knepley 
24161096aae1SMatthew Knepley   Level: intermediate
24171096aae1SMatthew Knepley 
24181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24191096aae1SMatthew Knepley @*/
2420d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2421d71ae5a4SJacob Faibussowitsch {
24221096aae1SMatthew Knepley   PetscFunctionBegin;
24230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24244f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
242585385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24271096aae1SMatthew Knepley }
24281096aae1SMatthew Knepley 
24299b94acceSBarry Smith /*@
2430f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24319b94acceSBarry Smith 
2432c3339decSBarry Smith   Collective
2433c7afd0dbSLois Curfman McInnes 
24349b94acceSBarry Smith   Input Parameters:
2435f6dfbefdSBarry Smith + snes - the `SNES` context
2436c7afd0dbSLois Curfman McInnes - x    - input vector
24379b94acceSBarry Smith 
24389b94acceSBarry Smith   Output Parameter:
2439f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24409b94acceSBarry Smith 
2441dc4c0fb0SBarry Smith   Level: developer
2442dc4c0fb0SBarry Smith 
244300677de2SStefano Zampini   Notes:
2444f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2445bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
244636851e7fSLois Curfman McInnes 
244700677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
244800677de2SStefano Zampini 
24491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24509b94acceSBarry Smith @*/
2451d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2452d71ae5a4SJacob Faibussowitsch {
24536cab3a1bSJed Brown   DM     dm;
2454942e3340SBarry Smith   DMSNES sdm;
24559b94acceSBarry Smith 
24563a40ed3dSBarry Smith   PetscFunctionBegin;
24570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24580700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24590700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2460c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2461c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2462e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2463184914b5SBarry Smith 
24649566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24659566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24660fdf79fbSJacob 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().");
246732f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
246848a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24699566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24708ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24718ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2472800f99ffSJeremy L Thompson     {
2473800f99ffSJeremy L Thompson       void           *ctx;
24748434afd1SBarry Smith       SNESFunctionFn *computefunction;
2475800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2476800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2477800f99ffSJeremy L Thompson     }
24789566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
247948a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24800fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24819566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24820fdf79fbSJacob Faibussowitsch   }
24831baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2484ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2485422a814eSBarry Smith   /*
2486422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2487422a814eSBarry Smith      propagate the value to all processes
2488422a814eSBarry Smith   */
2489f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
24903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24919b94acceSBarry Smith }
24929b94acceSBarry Smith 
2493c79ef259SPeter Brune /*@
24940b4b7b1cSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`.
2495bbc1464cSBarry Smith 
2496c3339decSBarry Smith   Collective
2497bbc1464cSBarry Smith 
2498bbc1464cSBarry Smith   Input Parameters:
2499f6dfbefdSBarry Smith + snes - the `SNES` context
2500bbc1464cSBarry Smith - x    - input vector
2501bbc1464cSBarry Smith 
2502bbc1464cSBarry Smith   Output Parameter:
25030b4b7b1cSBarry Smith . y - output vector
2504bbc1464cSBarry Smith 
2505dc4c0fb0SBarry Smith   Level: developer
2506dc4c0fb0SBarry Smith 
2507bbc1464cSBarry Smith   Notes:
2508420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2509bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2510bbc1464cSBarry Smith 
2511dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2512f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2513dd8e379bSPierre 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.
2514bbc1464cSBarry Smith 
25150b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()`
2516bbc1464cSBarry Smith @*/
2517d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2518d71ae5a4SJacob Faibussowitsch {
2519bbc1464cSBarry Smith   DM     dm;
2520bbc1464cSBarry Smith   DMSNES sdm;
2521bbc1464cSBarry Smith 
2522bbc1464cSBarry Smith   PetscFunctionBegin;
2523bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2524bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2525bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2526bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2527bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2528e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2529bbc1464cSBarry Smith 
25309566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25319566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25339566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2534bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2535bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2536792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25379566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2539bbc1464cSBarry Smith   snes->nfuncs++;
2540bbc1464cSBarry Smith   /*
2541bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2542bbc1464cSBarry Smith      propagate the value to all processes
2543bbc1464cSBarry Smith   */
2544f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2546bbc1464cSBarry Smith }
2547bbc1464cSBarry Smith 
2548bbc1464cSBarry Smith /*@
2549f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2550c79ef259SPeter Brune 
2551c3339decSBarry Smith   Collective
2552c79ef259SPeter Brune 
2553c79ef259SPeter Brune   Input Parameters:
2554f6dfbefdSBarry Smith + snes - the `SNES` context
2555c79ef259SPeter Brune . x    - input vector
2556c79ef259SPeter Brune - b    - rhs vector
2557c79ef259SPeter Brune 
2558c79ef259SPeter Brune   Output Parameter:
2559c79ef259SPeter Brune . x - new solution vector
2560c79ef259SPeter Brune 
2561dc4c0fb0SBarry Smith   Level: developer
2562dc4c0fb0SBarry Smith 
2563f6dfbefdSBarry Smith   Note:
2564f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2565c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2566c79ef259SPeter Brune   themselves.
2567c79ef259SPeter Brune 
25688434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2569c79ef259SPeter Brune @*/
2570d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2571d71ae5a4SJacob Faibussowitsch {
25726cab3a1bSJed Brown   DM     dm;
2573942e3340SBarry Smith   DMSNES sdm;
2574646217ecSPeter Brune 
2575646217ecSPeter Brune   PetscFunctionBegin;
2576646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2577064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2578064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2579064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2580064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2581e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25829566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25839566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25849566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25850fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25869566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2587792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25889566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2591646217ecSPeter Brune }
2592646217ecSPeter Brune 
2593494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2594494a190aSStefano Zampini {
2595494a190aSStefano Zampini   Vec          X;
2596494a190aSStefano Zampini   PetscScalar *g;
2597494a190aSStefano Zampini   PetscReal    f, f2;
2598494a190aSStefano Zampini   PetscInt     low, high, N, i;
2599494a190aSStefano Zampini   PetscBool    flg;
2600494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2601494a190aSStefano Zampini 
2602494a190aSStefano Zampini   PetscFunctionBegin;
2603494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2604494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2605494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2606494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2607494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2608494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2609494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2610494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2611494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2612494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2613494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2614494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2615494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2616494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2617494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2618494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2619494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2620494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2621494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2622494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2623494a190aSStefano Zampini   }
2624494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2625494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2626494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2627494a190aSStefano Zampini }
2628494a190aSStefano Zampini 
2629494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2630494a190aSStefano Zampini {
2631494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2632494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2633494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2634494a190aSStefano Zampini   PetscScalar       dot;
2635494a190aSStefano Zampini   MPI_Comm          comm;
2636494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2637494a190aSStefano Zampini   PetscViewerFormat format;
2638494a190aSStefano Zampini   PetscInt          tabs;
2639494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26408434afd1SBarry Smith   SNESObjectiveFn  *objective;
2641494a190aSStefano Zampini 
2642494a190aSStefano Zampini   PetscFunctionBegin;
2643494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2644494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2645494a190aSStefano Zampini 
2646494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2647494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2648494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2649494a190aSStefano Zampini   PetscOptionsEnd();
2650494a190aSStefano Zampini   if (!test) {
2651494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2652494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2653494a190aSStefano Zampini   }
2654494a190aSStefano Zampini 
2655494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2656494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2657494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2658494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2659494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2660494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2661494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2662494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2663494a190aSStefano Zampini   }
2664494a190aSStefano Zampini   if (!directionsprinted) {
2665494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2666494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2667494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2668494a190aSStefano Zampini   }
2669494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2670494a190aSStefano Zampini 
2671494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2672494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2673494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2674494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2675494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2676494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2677494a190aSStefano Zampini 
2678494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2679494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2680494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2681494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2682494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2683494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2684494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2685494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2686494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2687494a190aSStefano 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))));
2688494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2689494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2690494a190aSStefano Zampini 
2691494a190aSStefano Zampini   if (complete_print) {
2692494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2693494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2694494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2695494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2696494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2697494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2698494a190aSStefano Zampini   }
2699494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2700494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2701494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2702494a190aSStefano Zampini 
2703494a190aSStefano Zampini   if (complete_print) {
2704494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2705494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2706494a190aSStefano Zampini   }
2707494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2708494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2709494a190aSStefano Zampini }
2710494a190aSStefano Zampini 
2711*cbf8f02cSMatthew G. Knepley /*@
2712*cbf8f02cSMatthew G. Knepley   SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians
2713*cbf8f02cSMatthew G. Knepley 
2714*cbf8f02cSMatthew G. Knepley   Collective
2715*cbf8f02cSMatthew G. Knepley 
2716*cbf8f02cSMatthew G. Knepley   Input Parameters:
2717*cbf8f02cSMatthew G. Knepley . snes - the `SNES` context
2718*cbf8f02cSMatthew G. Knepley 
2719*cbf8f02cSMatthew G. Knepley   Output Parameters:
2720*cbf8f02cSMatthew G. Knepley + Jnorm    - the Frobenius norm of the computed Jacobian, or NULL
2721*cbf8f02cSMatthew G. Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or NULL
2722*cbf8f02cSMatthew G. Knepley 
2723*cbf8f02cSMatthew G. Knepley   Options Database Keys:
2724*cbf8f02cSMatthew G. Knepley + -snes_test_jacobian <optional threshold> - compare the user provided Jacobian with one compute via finite differences to check for errors.  If a threshold is given, display only those entries whose difference is greater than the threshold.
2725*cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view                 - display the user provided Jacobian, the finite difference Jacobian and the difference
2726*cbf8f02cSMatthew G. Knepley 
2727*cbf8f02cSMatthew G. Knepley   Level: developer
2728*cbf8f02cSMatthew G. Knepley 
2729*cbf8f02cSMatthew G. Knepley .seealso: [](ch_snes), `SNESSetJacobian()`, `SNESComputeJacobian()`
2730*cbf8f02cSMatthew G. Knepley @*/
2731*cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm)
2732d71ae5a4SJacob Faibussowitsch {
273312837594SBarry Smith   Mat               A, B, C, D, jacobian;
27344df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2735e885f1abSBarry Smith   PetscReal         nrm, gnorm;
273681e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27370e276705SLisandro Dalcin   MatType           mattype;
2738e885f1abSBarry Smith   PetscInt          m, n, M, N;
2739e885f1abSBarry Smith   void             *functx;
27402cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
27413325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2742e885f1abSBarry Smith   MPI_Comm          comm;
2743e885f1abSBarry Smith   PetscInt          tabs;
274412837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27453325ff46SBarry Smith   PetscViewerFormat format;
2746e885f1abSBarry Smith 
2747e885f1abSBarry Smith   PetscFunctionBegin;
2748d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
27509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27524ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27549566063dSJacob 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));
2755d0609cedSBarry Smith   PetscOptionsEnd();
27563ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2757e885f1abSBarry Smith 
27589566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27599566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27609566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27619566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27629566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
276312837594SBarry Smith   if (!complete_print && !directionsprinted) {
27649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
276612837594SBarry Smith   }
276712837594SBarry Smith   if (!directionsprinted) {
27689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
27699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
277012837594SBarry Smith     directionsprinted = PETSC_TRUE;
2771e885f1abSBarry Smith   }
27721baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2773e885f1abSBarry Smith 
27749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
277512837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
277612837594SBarry Smith   else jacobian = snes->jacobian_pre;
277712837594SBarry Smith 
27784df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
27794df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
27809566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
27814df93895SStefano Zampini 
2782a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
27839566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
27849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
27859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
278612837594SBarry Smith   while (jacobian) {
27872cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
27882cd624f9SStefano Zampini 
27892cd624f9SStefano Zampini     if (istranspose) {
27909566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
27912cd624f9SStefano Zampini       Jsave    = jacobian;
27922cd624f9SStefano Zampini       jacobian = JT;
27932cd624f9SStefano Zampini     }
27949566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
279512837594SBarry Smith     if (flg) {
279612837594SBarry Smith       A = jacobian;
27979566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
279812837594SBarry Smith     } else {
27999566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
280012837594SBarry Smith     }
2801e885f1abSBarry Smith 
28029566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
28039566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
28049566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
28059566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
28069566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
28079566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
28089566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
28099566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
28109566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2811e885f1abSBarry Smith 
28129566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28139566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
281412837594SBarry Smith 
28159566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28169566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28179566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28189566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28199566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
282012837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
28219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
282212837594SBarry Smith 
2823e885f1abSBarry Smith     if (complete_print) {
28249566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
28259566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
28269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
28279566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2828e885f1abSBarry Smith     }
2829e885f1abSBarry Smith 
2830df10fb39SFande Kong     if (threshold_print || complete_print) {
2831e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2832e885f1abSBarry Smith       PetscScalar       *cvals;
2833e885f1abSBarry Smith       const PetscInt    *bcols;
2834e885f1abSBarry Smith       const PetscScalar *bvals;
2835e885f1abSBarry Smith 
28369566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28379566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28389566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28399566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28409566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28419566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28420e276705SLisandro Dalcin 
28439566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28449566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2845e885f1abSBarry Smith 
2846e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28479566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28489566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2849e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
285023a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2851e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2852e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2853e885f1abSBarry Smith             cncols += 1;
2854e885f1abSBarry Smith           }
2855e885f1abSBarry Smith         }
285648a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28579566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28589566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2859e885f1abSBarry Smith       }
28609566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28619566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28639566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28649566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2865e885f1abSBarry Smith     }
28669566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
28679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
28689566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
28692cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
287012837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
287112837594SBarry Smith       jacobian = snes->jacobian_pre;
28729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
28739371c9d4SSatish Balay     } else jacobian = NULL;
287412837594SBarry Smith   }
28759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
28761baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2877648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
28789566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2879*cbf8f02cSMatthew G. Knepley 
2880*cbf8f02cSMatthew G. Knepley   if (Jnorm) *Jnorm = gnorm;
2881*cbf8f02cSMatthew G. Knepley   if (diffNorm) *diffNorm = nrm;
28823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2883e885f1abSBarry Smith }
2884e885f1abSBarry Smith 
288562fef451SLois Curfman McInnes /*@
2886f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
288762fef451SLois Curfman McInnes 
2888c3339decSBarry Smith   Collective
2889c7afd0dbSLois Curfman McInnes 
289062fef451SLois Curfman McInnes   Input Parameters:
2891f6dfbefdSBarry Smith + snes - the `SNES` context
2892e4094ef1SJacob Faibussowitsch - X    - input vector
289362fef451SLois Curfman McInnes 
289462fef451SLois Curfman McInnes   Output Parameters:
2895c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2896420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2897fee21e36SBarry Smith 
2898e35cf81dSBarry Smith   Options Database Keys:
289967b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
290067b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2901455a5933SJed 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.
2902455a5933SJed 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
2903693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2904693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2905693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
29067addb90fSBarry Smith . -snes_compare_operator                   - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner
290794d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2908a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2909c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2910dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2911dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2912a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2913a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2914c01495d3SJed Brown 
2915dc4c0fb0SBarry Smith   Level: developer
2916dc4c0fb0SBarry Smith 
2917f6dfbefdSBarry Smith   Note:
291862fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
291962fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
292062fef451SLois Curfman McInnes 
2921420bcc1bSBarry Smith   Developer Note:
2922dc4c0fb0SBarry 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
2923420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2924e885f1abSBarry Smith 
29251cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
292662fef451SLois Curfman McInnes @*/
2927d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2928d71ae5a4SJacob Faibussowitsch {
2929ace3abfcSBarry Smith   PetscBool flag;
29306cab3a1bSJed Brown   DM        dm;
2931942e3340SBarry Smith   DMSNES    sdm;
2932e0e3a89bSBarry Smith   KSP       ksp;
29333a40ed3dSBarry Smith 
29343a40ed3dSBarry Smith   PetscFunctionBegin;
29350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29360700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2937c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2938e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29399566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29409566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29413232da50SPeter Brune 
294201c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2943fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2944fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2945f5af7f23SKarl Rupp 
29469566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2947fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29489566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29499566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2950ebd3b9afSBarry Smith     if (flag) {
29519566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29529566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2953ebd3b9afSBarry Smith     }
29543ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
295537ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
295663a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29579566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2958ebd3b9afSBarry Smith     if (flag) {
29599566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29609566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2961ebd3b9afSBarry Smith     }
29623ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2963e35cf81dSBarry Smith   }
2964efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29659566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29669566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29673ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2968d728fb7dSPeter Brune   }
2969e35cf81dSBarry Smith 
29709566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
29719566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2972800f99ffSJeremy L Thompson   {
2973800f99ffSJeremy L Thompson     void           *ctx;
29748434afd1SBarry Smith     SNESJacobianFn *J;
2975800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2976800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2977800f99ffSJeremy L Thompson   }
29789566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
29799566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
298028d58a37SPierre Jolivet 
29817addb90fSBarry Smith   /* attach latest linearization point to the matrix used to construct the preconditioner */
29829566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2983a8054027SBarry Smith 
2984e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
29859566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
29863b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
29879566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
29889566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
29893b4f5425SBarry Smith     snes->lagpreconditioner = -1;
29903b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
29919566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
29929566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
299337ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
299463a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
29959566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2996d1e9a80fSBarry Smith   } else {
29979566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
29989566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2999a8054027SBarry Smith   }
3000a8054027SBarry Smith 
30014df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
30024df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
30034df93895SStefano Zampini   {
30044df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
30054df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
30064df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
30074df93895SStefano Zampini 
30084df93895SStefano Zampini     snes->vec_sol      = X;
30094df93895SStefano Zampini     snes->jacobian     = A;
30104df93895SStefano Zampini     snes->jacobian_pre = B;
3011494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
3012*cbf8f02cSMatthew G. Knepley     PetscCall(SNESTestJacobian(snes, NULL, NULL));
3013494a190aSStefano Zampini 
30144df93895SStefano Zampini     snes->vec_sol      = xsave;
30154df93895SStefano Zampini     snes->jacobian     = jacobiansave;
30164df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
30174df93895SStefano Zampini   }
30184df93895SStefano Zampini 
3019693365a8SJed Brown   {
3020693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3021648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3022648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3023648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3024648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3025693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
30260298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
3027693365a8SJed Brown       PetscViewer vdraw, vstdout;
30286b3a5b13SJed Brown       PetscBool   flg;
3029693365a8SJed Brown       if (flag_operator) {
30309566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3031693365a8SJed Brown         Bexp = Bexp_mine;
3032693365a8SJed Brown       } else {
30337addb90fSBarry Smith         /* See if the matrix used to construct the preconditioner can be viewed and added directly */
30349566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
303594ab13aaSBarry Smith         if (flg) Bexp = B;
3036693365a8SJed Brown         else {
3037693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30389566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3039693365a8SJed Brown           Bexp = Bexp_mine;
3040693365a8SJed Brown         }
3041693365a8SJed Brown       }
30429566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30439566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3045693365a8SJed Brown       if (flag_draw || flag_contour) {
30469566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30479566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30480298fd71SBarry Smith       } else vdraw = NULL;
30499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30509566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30519566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30539566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30549566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30559566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30579566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3058693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30599566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30609566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30619566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3062693365a8SJed Brown       }
30639566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30649566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30659566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3067693365a8SJed Brown     }
3068693365a8SJed Brown   }
30694c30e9fbSJed Brown   {
30706719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
30716719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3072648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3073648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3074648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3075648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3076648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
307727b0f280SBarry Smith     if (flag_threshold) {
30789566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
30799566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
308027b0f280SBarry Smith     }
30816719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
30824c30e9fbSJed Brown       Mat             Bfd;
30834c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3084335efc43SPeter Brune       MatColoring     coloring;
30854c30e9fbSJed Brown       ISColoring      iscoloring;
30864c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
30878434afd1SBarry Smith       SNESFunctionFn *func;
30884c30e9fbSJed Brown       void           *funcctx;
30896719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
30904c30e9fbSJed Brown 
30919566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
30929566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
30939566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
30949566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
30959566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
30969566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
30979566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
30989566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30999566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
31009566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
31014c30e9fbSJed Brown 
31024c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
31039566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
31042ba42892SBarry Smith       PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx));
31059566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
31069566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
31079566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31089566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
31099566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
31104c30e9fbSJed Brown 
31119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
31124c30e9fbSJed Brown       if (flag_draw || flag_contour) {
31139566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31149566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31150298fd71SBarry Smith       } else vdraw = NULL;
31169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31179566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
31189566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
31199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31209566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31219566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
31229566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31239566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31249566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31259566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31279566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31284c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
31299566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31309566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
31319566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
31324c30e9fbSJed Brown       }
31339566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31346719d8e4SJed Brown 
31356719d8e4SJed Brown       if (flag_threshold) {
31366719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31379566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31389566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31396719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31406719d8e4SJed Brown           const PetscScalar *ba, *ca;
31416719d8e4SJed Brown           const PetscInt    *bj, *cj;
31426719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31436719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31449566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31459566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31465f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31476719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31486719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31496719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31506719d8e4SJed Brown               maxentrycol = bj[j];
31516719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31526719d8e4SJed Brown             }
31536719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31546719d8e4SJed Brown               maxdiffcol = bj[j];
31556719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31566719d8e4SJed Brown             }
31576719d8e4SJed Brown             if (rdiff > maxrdiff) {
31586719d8e4SJed Brown               maxrdiffcol = bj[j];
31596719d8e4SJed Brown               maxrdiff    = rdiff;
31606719d8e4SJed Brown             }
31616719d8e4SJed Brown           }
31626719d8e4SJed Brown           if (maxrdiff > 1) {
316363a3b9bcSJacob 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));
31646719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31656719d8e4SJed Brown               PetscReal rdiff;
31666719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
316748a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
31686719d8e4SJed Brown             }
316963a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
31706719d8e4SJed Brown           }
31719566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
31729566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
31736719d8e4SJed Brown         }
31746719d8e4SJed Brown       }
31759566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
31769566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
31774c30e9fbSJed Brown     }
31784c30e9fbSJed Brown   }
31793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31809b94acceSBarry Smith }
31819b94acceSBarry Smith 
31829b94acceSBarry Smith /*@C
31839b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3184044dda88SLois Curfman McInnes   location to store the matrix.
31859b94acceSBarry Smith 
3186c3339decSBarry Smith   Logically Collective
3187c7afd0dbSLois Curfman McInnes 
31889b94acceSBarry Smith   Input Parameters:
3189f6dfbefdSBarry Smith + snes - the `SNES` context
3190e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3191dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
31928434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3193c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3194dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3195dc4c0fb0SBarry Smith 
3196dc4c0fb0SBarry Smith   Level: beginner
31979b94acceSBarry Smith 
31989b94acceSBarry Smith   Notes:
3199dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
320016913363SBarry Smith   each matrix.
320116913363SBarry Smith 
3202dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3203dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3204895c21f2SBarry Smith 
3205dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3206f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3207a8a26c1eSJed Brown 
3208c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3209f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3210c3cc8fd1SJed Brown 
32111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
32128434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32139b94acceSBarry Smith @*/
32148434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3215d71ae5a4SJacob Faibussowitsch {
32166cab3a1bSJed Brown   DM dm;
32173a7fca6bSBarry Smith 
32183a40ed3dSBarry Smith   PetscFunctionBegin;
32190700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3220e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3221e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3222e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3223e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32249566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32259566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3226e5d3d808SBarry Smith   if (Amat) {
32279566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
32289566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3229f5af7f23SKarl Rupp 
3230e5d3d808SBarry Smith     snes->jacobian = Amat;
32313a7fca6bSBarry Smith   }
3232e5d3d808SBarry Smith   if (Pmat) {
32339566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
32349566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3235f5af7f23SKarl Rupp 
3236e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32373a7fca6bSBarry Smith   }
32383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32399b94acceSBarry Smith }
324062fef451SLois Curfman McInnes 
3241c2aafc4cSSatish Balay /*@C
3242b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3243b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3244b4fd4287SBarry Smith 
3245420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3246c7afd0dbSLois Curfman McInnes 
3247b4fd4287SBarry Smith   Input Parameter:
3248b4fd4287SBarry Smith . snes - the nonlinear solver context
3249b4fd4287SBarry Smith 
3250b4fd4287SBarry Smith   Output Parameters:
3251dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3252dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32538434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3254dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3255fee21e36SBarry Smith 
325636851e7fSLois Curfman McInnes   Level: advanced
325736851e7fSLois Curfman McInnes 
32588434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3259b4fd4287SBarry Smith @*/
32608434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3261d71ae5a4SJacob Faibussowitsch {
32626cab3a1bSJed Brown   DM dm;
32636cab3a1bSJed Brown 
32643a40ed3dSBarry Smith   PetscFunctionBegin;
32650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3266e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3267e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
32689566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3269800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
32703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3271b4fd4287SBarry Smith }
3272b4fd4287SBarry Smith 
3273d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3274d71ae5a4SJacob Faibussowitsch {
327558b371f3SBarry Smith   DM     dm;
327658b371f3SBarry Smith   DMSNES sdm;
327758b371f3SBarry Smith 
327858b371f3SBarry Smith   PetscFunctionBegin;
32799566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32809566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
328158b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
328258b371f3SBarry Smith     DM        dm;
328358b371f3SBarry Smith     PetscBool isdense, ismf;
328458b371f3SBarry Smith 
32859566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32869566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
32879566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
328858b371f3SBarry Smith     if (isdense) {
32899566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
329058b371f3SBarry Smith     } else if (!ismf) {
32919566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
329258b371f3SBarry Smith     }
329358b371f3SBarry Smith   }
32943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
329558b371f3SBarry Smith }
329658b371f3SBarry Smith 
32979b94acceSBarry Smith /*@
32989b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
32990b4b7b1cSBarry Smith   of a nonlinear solver `SNESSolve()`.
33009b94acceSBarry Smith 
3301c3339decSBarry Smith   Collective
3302fee21e36SBarry Smith 
33032fe279fdSBarry Smith   Input Parameter:
3304f6dfbefdSBarry Smith . snes - the `SNES` context
3305c7afd0dbSLois Curfman McInnes 
3306dc4c0fb0SBarry Smith   Level: advanced
3307dc4c0fb0SBarry Smith 
3308f6dfbefdSBarry Smith   Note:
33090b4b7b1cSBarry Smith   For basic use of the `SNES` solvers the user does not need to explicitly call
3310f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3311f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3312f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3313f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3314272ac6f2SLois Curfman McInnes 
33150b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()`
33169b94acceSBarry Smith @*/
3317d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3318d71ae5a4SJacob Faibussowitsch {
33196cab3a1bSJed Brown   DM             dm;
3320942e3340SBarry Smith   DMSNES         sdm;
3321c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
33226e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
33239b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
33249b5c1c08SStefano Zampini   Vec            f, fpc;
33259b5c1c08SStefano Zampini   void          *funcctx;
33269b5c1c08SStefano Zampini   void          *jacctx, *appctx;
33279b5c1c08SStefano Zampini   Mat            j, jpre;
33286b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33296b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33308434afd1SBarry Smith   SNESFunctionFn *func;
33318434afd1SBarry Smith   SNESJacobianFn *jac;
33323a40ed3dSBarry Smith 
33333a40ed3dSBarry Smith   PetscFunctionBegin;
33340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33353ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3336fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33379b94acceSBarry Smith 
333848a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
333985385478SLisandro Dalcin 
33409566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
334158c9b817SLisandro Dalcin 
33429566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33439566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33449566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
334558b371f3SBarry Smith 
334648a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3347efd51863SBarry Smith 
334848a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3349b710008aSBarry Smith 
3350d8d34be6SBarry Smith   if (snes->linesearch) {
33519566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33529566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3353d8d34be6SBarry Smith   }
33549e764e56SPeter Brune 
33559b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3356b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3357172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3358172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3359172a4300SPeter Brune   }
3360d8f46077SPeter Brune 
3361efd4aadfSBarry Smith   if (snes->npc) {
33626e2a1849SPeter Brune     /* copy the DM over */
33639566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33649566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33656e2a1849SPeter Brune 
33669566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33679566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
33689566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
33699566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
33709566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
33719566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
33729566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
33739b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
33749566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
33756e2a1849SPeter Brune 
33766e2a1849SPeter Brune     /* copy the function pointers over */
33779566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
33786e2a1849SPeter Brune 
33796e2a1849SPeter Brune     /* default to 1 iteration */
33809566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3381efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
33829566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3383a9936a0cSPeter Brune     } else {
33849566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3385a9936a0cSPeter Brune     }
33869566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
33876e2a1849SPeter Brune 
33886e2a1849SPeter Brune     /* copy the line search context over */
3389d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
33909566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
33919566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
33929566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
33939566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
33949566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
33959566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
33969566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
33976e2a1849SPeter Brune     }
3398d8d34be6SBarry Smith   }
33991baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
3400835f2295SStefano Zampini   if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx));
34016e2a1849SPeter Brune 
340237ec4e1aSPeter Brune   snes->jac_iter = 0;
340337ec4e1aSPeter Brune   snes->pre_iter = 0;
340437ec4e1aSPeter Brune 
3405dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
340658c9b817SLisandro Dalcin 
34079566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
340858b371f3SBarry Smith 
3409b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
34106c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3411d8d34be6SBarry Smith       if (snes->linesearch) {
34129566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
34139566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34146c67d002SPeter Brune       }
34156c67d002SPeter Brune     }
3416d8d34be6SBarry Smith   }
3417fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34187aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
34193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34209b94acceSBarry Smith }
34219b94acceSBarry Smith 
342237596af1SLisandro Dalcin /*@
34230b4b7b1cSBarry Smith   SNESReset - Resets a `SNES` context to the state it was in before `SNESSetUp()` was called and removes any allocated `Vec` and `Mat` from its data structures
342437596af1SLisandro Dalcin 
3425c3339decSBarry Smith   Collective
342637596af1SLisandro Dalcin 
342737596af1SLisandro Dalcin   Input Parameter:
34280b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
342937596af1SLisandro Dalcin 
3430d25893d9SBarry Smith   Level: intermediate
3431d25893d9SBarry Smith 
343295452b02SPatrick Sanan   Notes:
34330b4b7b1cSBarry Smith   Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain.
34340b4b7b1cSBarry Smith 
3435f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
343637596af1SLisandro Dalcin 
3437f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3438f6dfbefdSBarry Smith 
34391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
344037596af1SLisandro Dalcin @*/
3441d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3442d71ae5a4SJacob Faibussowitsch {
344337596af1SLisandro Dalcin   PetscFunctionBegin;
344437596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
344549abdd8aSBarry Smith   if (snes->ops->ctxdestroy && snes->ctx) {
3446835f2295SStefano Zampini     PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx));
344749abdd8aSBarry Smith     snes->ctx = NULL;
3448d25893d9SBarry Smith   }
34491baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34508a23116dSBarry Smith 
3451dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34521baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34539e764e56SPeter Brune 
34541baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34559e764e56SPeter Brune 
34569566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34579566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34599566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34639566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34649566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3465f5af7f23SKarl Rupp 
346640fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
346740fdac6aSLawrence Mitchell 
346837596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
346937596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
34703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
347137596af1SLisandro Dalcin }
347237596af1SLisandro Dalcin 
347352baeb72SSatish Balay /*@
347436d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
347536d43d94SBarry Smith   removes the default viewer.
3476c4421ceaSFande Kong 
3477c3339decSBarry Smith   Collective
3478c4421ceaSFande Kong 
3479c4421ceaSFande Kong   Input Parameter:
34800b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
3481c4421ceaSFande Kong 
3482c4421ceaSFande Kong   Level: intermediate
3483c4421ceaSFande Kong 
3484420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3485c4421ceaSFande Kong @*/
3486d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3487d71ae5a4SJacob Faibussowitsch {
3488c4421ceaSFande Kong   PetscInt i;
3489c4421ceaSFande Kong 
3490c4421ceaSFande Kong   PetscFunctionBegin;
3491c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3492c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
349348a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3494c4421ceaSFande Kong   }
3495c4421ceaSFande Kong   snes->numberreasonviews = 0;
3496648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
34973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3498c4421ceaSFande Kong }
3499c4421ceaSFande Kong 
35000764c050SBarry Smith /*@
35019b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3502f6dfbefdSBarry Smith   with `SNESCreate()`.
35039b94acceSBarry Smith 
3504c3339decSBarry Smith   Collective
3505c7afd0dbSLois Curfman McInnes 
35069b94acceSBarry Smith   Input Parameter:
3507f6dfbefdSBarry Smith . snes - the `SNES` context
35089b94acceSBarry Smith 
350936851e7fSLois Curfman McInnes   Level: beginner
351036851e7fSLois Curfman McInnes 
35111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
35129b94acceSBarry Smith @*/
3513d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3514d71ae5a4SJacob Faibussowitsch {
35153a40ed3dSBarry Smith   PetscFunctionBegin;
35163ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3517f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3518f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
35199371c9d4SSatish Balay     *snes = NULL;
35203ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
35219371c9d4SSatish Balay   }
3522d4bb536fSBarry Smith 
3523f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
35249566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
35256b8b9a38SLisandro Dalcin 
3526e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
35279566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3528f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
35296d4c513bSLisandro Dalcin 
35309566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
35319566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
35329566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
35339566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35346b8b9a38SLisandro Dalcin 
35359566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
353648a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
353748a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3538f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3539f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35409566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35429b94acceSBarry Smith }
35439b94acceSBarry Smith 
35449b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35459b94acceSBarry Smith 
3546a8054027SBarry Smith /*@
35470b4b7b1cSBarry Smith   SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`.
3548a8054027SBarry Smith 
3549c3339decSBarry Smith   Logically Collective
3550a8054027SBarry Smith 
3551a8054027SBarry Smith   Input Parameters:
3552f6dfbefdSBarry Smith + snes - the `SNES` context
3553d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35543b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3555a8054027SBarry Smith 
3556a8054027SBarry Smith   Options Database Keys:
3557420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35583d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3559420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35603d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3561a8054027SBarry Smith 
3562dc4c0fb0SBarry Smith   Level: intermediate
3563dc4c0fb0SBarry Smith 
3564420bcc1bSBarry Smith   Notes:
3565a8054027SBarry Smith   The default is 1
3566420bcc1bSBarry Smith 
3567f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3568d8e291bfSBarry Smith 
3569f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3570a8054027SBarry Smith 
35713201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3572f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3573a8054027SBarry Smith @*/
3574d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3575d71ae5a4SJacob Faibussowitsch {
3576a8054027SBarry Smith   PetscFunctionBegin;
35770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35785f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35795f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3580c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3581a8054027SBarry Smith   snes->lagpreconditioner = lag;
35823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3583a8054027SBarry Smith }
3584a8054027SBarry Smith 
3585efd51863SBarry Smith /*@
3586f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3587efd51863SBarry Smith 
3588c3339decSBarry Smith   Logically Collective
3589efd51863SBarry Smith 
3590efd51863SBarry Smith   Input Parameters:
3591f6dfbefdSBarry Smith + snes  - the `SNES` context
3592efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3593efd51863SBarry Smith 
3594f6dfbefdSBarry Smith   Options Database Key:
359567b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3596efd51863SBarry Smith 
3597efd51863SBarry Smith   Level: intermediate
3598efd51863SBarry Smith 
35990b4b7b1cSBarry Smith   Notes:
36000b4b7b1cSBarry Smith   Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement.
36010b4b7b1cSBarry Smith 
3602f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3603c0df2a02SJed Brown 
36043201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
360554c05997SPierre Jolivet           `SNESSetDM()`, `SNESSolve()`
3606efd51863SBarry Smith @*/
3607d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3608d71ae5a4SJacob Faibussowitsch {
3609efd51863SBarry Smith   PetscFunctionBegin;
3610efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3611efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3612efd51863SBarry Smith   snes->gridsequence = steps;
36133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3614efd51863SBarry Smith }
3615efd51863SBarry Smith 
3616fa19ca70SBarry Smith /*@
3617f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3618fa19ca70SBarry Smith 
3619c3339decSBarry Smith   Logically Collective
3620fa19ca70SBarry Smith 
3621fa19ca70SBarry Smith   Input Parameter:
3622f6dfbefdSBarry Smith . snes - the `SNES` context
3623fa19ca70SBarry Smith 
3624fa19ca70SBarry Smith   Output Parameter:
3625fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3626fa19ca70SBarry Smith 
3627fa19ca70SBarry Smith   Level: intermediate
3628fa19ca70SBarry Smith 
36293201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3630fa19ca70SBarry Smith @*/
3631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3632d71ae5a4SJacob Faibussowitsch {
3633fa19ca70SBarry Smith   PetscFunctionBegin;
3634fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3635fa19ca70SBarry Smith   *steps = snes->gridsequence;
36363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3637fa19ca70SBarry Smith }
3638fa19ca70SBarry Smith 
3639a8054027SBarry Smith /*@
3640f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3641a8054027SBarry Smith 
36423f9fe445SBarry Smith   Not Collective
3643a8054027SBarry Smith 
3644a8054027SBarry Smith   Input Parameter:
3645f6dfbefdSBarry Smith . snes - the `SNES` context
3646a8054027SBarry Smith 
3647a8054027SBarry Smith   Output Parameter:
3648a8054027SBarry 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
36493b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3650a8054027SBarry Smith 
3651dc4c0fb0SBarry Smith   Level: intermediate
3652dc4c0fb0SBarry Smith 
3653a8054027SBarry Smith   Notes:
3654a8054027SBarry Smith   The default is 1
3655f6dfbefdSBarry Smith 
3656a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3657a8054027SBarry Smith 
36583201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3659a8054027SBarry Smith @*/
3660d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3661d71ae5a4SJacob Faibussowitsch {
3662a8054027SBarry Smith   PetscFunctionBegin;
36630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3664a8054027SBarry Smith   *lag = snes->lagpreconditioner;
36653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3666a8054027SBarry Smith }
3667a8054027SBarry Smith 
3668e35cf81dSBarry Smith /*@
3669f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3670e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3671e35cf81dSBarry Smith 
3672c3339decSBarry Smith   Logically Collective
3673e35cf81dSBarry Smith 
3674e35cf81dSBarry Smith   Input Parameters:
3675f6dfbefdSBarry Smith + snes - the `SNES` context
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
3677fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3678e35cf81dSBarry Smith 
3679e35cf81dSBarry Smith   Options Database Keys:
368079a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36813d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
368279a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36833d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3684e35cf81dSBarry Smith 
3685dc4c0fb0SBarry Smith   Level: intermediate
3686dc4c0fb0SBarry Smith 
3687e35cf81dSBarry Smith   Notes:
3688e35cf81dSBarry Smith   The default is 1
3689f6dfbefdSBarry Smith 
3690e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3691f6dfbefdSBarry Smith 
3692fe3ffe1eSBarry 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
3693fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3694e35cf81dSBarry Smith 
36953201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3696e35cf81dSBarry Smith @*/
3697d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3698d71ae5a4SJacob Faibussowitsch {
3699e35cf81dSBarry Smith   PetscFunctionBegin;
37000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
37015f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
37025f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3703c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3704e35cf81dSBarry Smith   snes->lagjacobian = lag;
37053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3706e35cf81dSBarry Smith }
3707e35cf81dSBarry Smith 
3708e35cf81dSBarry Smith /*@
3709f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3710e35cf81dSBarry Smith 
37113f9fe445SBarry Smith   Not Collective
3712e35cf81dSBarry Smith 
3713e35cf81dSBarry Smith   Input Parameter:
3714f6dfbefdSBarry Smith . snes - the `SNES` context
3715e35cf81dSBarry Smith 
3716e35cf81dSBarry Smith   Output Parameter:
3717e35cf81dSBarry 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
3718e35cf81dSBarry Smith          the Jacobian is built etc.
3719e35cf81dSBarry Smith 
3720dc4c0fb0SBarry Smith   Level: intermediate
3721dc4c0fb0SBarry Smith 
3722e35cf81dSBarry Smith   Notes:
3723e35cf81dSBarry Smith   The default is 1
3724f6dfbefdSBarry Smith 
3725f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3726e35cf81dSBarry Smith 
37273201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3728e35cf81dSBarry Smith 
3729e35cf81dSBarry Smith @*/
3730d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3731d71ae5a4SJacob Faibussowitsch {
3732e35cf81dSBarry Smith   PetscFunctionBegin;
37330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3734e35cf81dSBarry Smith   *lag = snes->lagjacobian;
37353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3736e35cf81dSBarry Smith }
3737e35cf81dSBarry Smith 
373837ec4e1aSPeter Brune /*@
3739f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
374037ec4e1aSPeter Brune 
3741c3339decSBarry Smith   Logically collective
374237ec4e1aSPeter Brune 
3743d8d19677SJose E. Roman   Input Parameters:
3744f6dfbefdSBarry Smith + snes - the `SNES` context
37459d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
374637ec4e1aSPeter Brune 
374737ec4e1aSPeter Brune   Options Database Keys:
374879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37493d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
375079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37513d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37523d5a8a6aSBarry Smith 
3753dc4c0fb0SBarry Smith   Level: advanced
3754dc4c0fb0SBarry Smith 
375595452b02SPatrick Sanan   Notes:
3756420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3757f6dfbefdSBarry Smith 
375895452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
375937ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
376037ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
376137ec4e1aSPeter Brune 
376242747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
376337ec4e1aSPeter Brune @*/
3764d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3765d71ae5a4SJacob Faibussowitsch {
376637ec4e1aSPeter Brune   PetscFunctionBegin;
376737ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
376837ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
376937ec4e1aSPeter Brune   snes->lagjac_persist = flg;
37703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377137ec4e1aSPeter Brune }
377237ec4e1aSPeter Brune 
377337ec4e1aSPeter Brune /*@
3774d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
377537ec4e1aSPeter Brune 
3776c3339decSBarry Smith   Logically Collective
377737ec4e1aSPeter Brune 
3778d8d19677SJose E. Roman   Input Parameters:
3779f6dfbefdSBarry Smith + snes - the `SNES` context
37809d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
378137ec4e1aSPeter Brune 
378237ec4e1aSPeter Brune   Options Database Keys:
378379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37843d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
378579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37863d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
378737ec4e1aSPeter Brune 
3788dc4c0fb0SBarry Smith   Level: developer
3789dc4c0fb0SBarry Smith 
379095452b02SPatrick Sanan   Notes:
3791420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3792f6dfbefdSBarry Smith 
379395452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
379437ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
379537ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
379637ec4e1aSPeter Brune 
37971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
379837ec4e1aSPeter Brune @*/
3799d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3800d71ae5a4SJacob Faibussowitsch {
380137ec4e1aSPeter Brune   PetscFunctionBegin;
380237ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
380337ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
380437ec4e1aSPeter Brune   snes->lagpre_persist = flg;
38053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
380637ec4e1aSPeter Brune }
380737ec4e1aSPeter Brune 
38089b94acceSBarry Smith /*@
3809f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3810be5caee7SBarry Smith 
3811c3339decSBarry Smith   Logically Collective
3812be5caee7SBarry Smith 
3813be5caee7SBarry Smith   Input Parameters:
3814f6dfbefdSBarry Smith + snes  - the `SNES` context
3815f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3816be5caee7SBarry Smith 
3817f6dfbefdSBarry Smith   Options Database Key:
3818be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3819be5caee7SBarry Smith 
3820dc4c0fb0SBarry Smith   Level: intermediate
3821dc4c0fb0SBarry Smith 
3822f6dfbefdSBarry Smith   Note:
3823f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3824be5caee7SBarry Smith 
38253201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3826be5caee7SBarry Smith @*/
3827d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3828d71ae5a4SJacob Faibussowitsch {
3829be5caee7SBarry Smith   PetscFunctionBegin;
3830be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3831be5caee7SBarry Smith   snes->forceiteration = force;
38323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3833be5caee7SBarry Smith }
3834be5caee7SBarry Smith 
383585216dc7SFande Kong /*@
3836f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
383785216dc7SFande Kong 
3838c3339decSBarry Smith   Logically Collective
383985216dc7SFande Kong 
38402fe279fdSBarry Smith   Input Parameter:
3841f6dfbefdSBarry Smith . snes - the `SNES` context
384285216dc7SFande Kong 
384385216dc7SFande Kong   Output Parameter:
3844dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
384585216dc7SFande Kong 
384606dd6b0eSSatish Balay   Level: intermediate
384706dd6b0eSSatish Balay 
38483201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
384985216dc7SFande Kong @*/
3850d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3851d71ae5a4SJacob Faibussowitsch {
385285216dc7SFande Kong   PetscFunctionBegin;
385385216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
385485216dc7SFande Kong   *force = snes->forceiteration;
38553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
385685216dc7SFande Kong }
3857be5caee7SBarry Smith 
3858be5caee7SBarry Smith /*@
38590b4b7b1cSBarry Smith   SNESSetTolerances - Sets various parameters used in `SNES` convergence tests.
38609b94acceSBarry Smith 
3861c3339decSBarry Smith   Logically Collective
3862c7afd0dbSLois Curfman McInnes 
38639b94acceSBarry Smith   Input Parameters:
3864f6dfbefdSBarry Smith + snes   - the `SNES` context
38650b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $
38660b4b7b1cSBarry Smith . rtol   - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $
38675358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
38680b4b7b1cSBarry Smith . maxit  - the maximum number of iterations allowed in the solver, default 50.
38690b4b7b1cSBarry Smith - maxf   - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3870fee21e36SBarry Smith 
387133174efeSLois Curfman McInnes   Options Database Keys:
387277e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
387377e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
387477e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
387577e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
387677e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
38779b94acceSBarry Smith 
387836851e7fSLois Curfman McInnes   Level: intermediate
387936851e7fSLois Curfman McInnes 
388077e5a1f9SBarry Smith   Note:
388177e5a1f9SBarry Smith   All parameters must be non-negative
388277e5a1f9SBarry Smith 
388377e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
388477e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
388577e5a1f9SBarry Smith 
388677e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
388777e5a1f9SBarry Smith 
388877e5a1f9SBarry Smith   Fortran Note:
388977e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
389077e5a1f9SBarry Smith 
38913201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
38929b94acceSBarry Smith @*/
3893d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3894d71ae5a4SJacob Faibussowitsch {
38953a40ed3dSBarry Smith   PetscFunctionBegin;
38960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3897c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3898c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3899c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3900c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3901c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3902c5eb9154SBarry Smith 
390377e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
390477e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
390577e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
39065f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3907ab54825eSJed Brown     snes->abstol = abstol;
3908ab54825eSJed Brown   }
390977e5a1f9SBarry Smith 
391077e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
391177e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
391277e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
39135f80ce2aSJacob 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);
3914ab54825eSJed Brown     snes->rtol = rtol;
3915ab54825eSJed Brown   }
391677e5a1f9SBarry Smith 
391777e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
391877e5a1f9SBarry Smith     snes->stol = snes->default_stol;
391977e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
39205f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3921c60f73f4SPeter Brune     snes->stol = stol;
3922ab54825eSJed Brown   }
392377e5a1f9SBarry Smith 
3924835f2295SStefano Zampini   if (maxit == PETSC_DETERMINE) {
392577e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
3926835f2295SStefano Zampini   } else if (maxit == PETSC_UNLIMITED) {
392777e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
392877e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
392963a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3930ab54825eSJed Brown     snes->max_its = maxit;
3931ab54825eSJed Brown   }
393277e5a1f9SBarry Smith 
3933835f2295SStefano Zampini   if (maxf == PETSC_DETERMINE) {
393477e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
3935835f2295SStefano Zampini   } else if (maxf == PETSC_UNLIMITED || maxf == -1) {
393677e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
393777e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
393877e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3939ab54825eSJed Brown     snes->max_funcs = maxf;
3940ab54825eSJed Brown   }
39413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39429b94acceSBarry Smith }
39439b94acceSBarry Smith 
3944e4d06f11SPatrick Farrell /*@
3945f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3946e4d06f11SPatrick Farrell 
3947c3339decSBarry Smith   Logically Collective
3948e4d06f11SPatrick Farrell 
3949e4d06f11SPatrick Farrell   Input Parameters:
3950f6dfbefdSBarry Smith + snes   - the `SNES` context
39510b4b7b1cSBarry Smith - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test. If the residual norm $ F(x^n) \ge divtol * F(x^0) $ the solver
39520b4b7b1cSBarry Smith            is stopped due to divergence.
3953e4d06f11SPatrick Farrell 
3954f6dfbefdSBarry Smith   Options Database Key:
3955dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3956e4d06f11SPatrick Farrell 
3957e4d06f11SPatrick Farrell   Level: intermediate
3958e4d06f11SPatrick Farrell 
395977e5a1f9SBarry Smith   Notes:
396077e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
3961e5cd489fSStefano Zampini 
396277e5a1f9SBarry Smith   Fortran Note:
396377e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
396477e5a1f9SBarry Smith 
396577e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
3966e4d06f11SPatrick Farrell @*/
3967d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3968d71ae5a4SJacob Faibussowitsch {
3969e4d06f11SPatrick Farrell   PetscFunctionBegin;
3970e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3971e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
397277e5a1f9SBarry Smith 
397377e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
397477e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
397577e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
397677e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
397777e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
397877e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
397977e5a1f9SBarry Smith     snes->divtol = divtol;
398077e5a1f9SBarry Smith   }
39813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3982e4d06f11SPatrick Farrell }
3983e4d06f11SPatrick Farrell 
39849b94acceSBarry Smith /*@
39850b4b7b1cSBarry Smith   SNESGetTolerances - Gets various parameters used in `SNES` convergence tests.
398633174efeSLois Curfman McInnes 
3987c7afd0dbSLois Curfman McInnes   Not Collective
3988c7afd0dbSLois Curfman McInnes 
398977e5a1f9SBarry Smith   Input Parameter:
399077e5a1f9SBarry Smith . snes - the `SNES` context
399177e5a1f9SBarry Smith 
399277e5a1f9SBarry Smith   Output Parameters:
39930b4b7b1cSBarry Smith + atol  - the absolute convergence tolerance
39940b4b7b1cSBarry Smith . rtol  - the relative convergence tolerance
399577e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
39960b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed
39970b4b7b1cSBarry Smith - maxf  - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound
3998fee21e36SBarry Smith 
399936851e7fSLois Curfman McInnes   Level: intermediate
400036851e7fSLois Curfman McInnes 
40010b4b7b1cSBarry Smith   Notes:
40020b4b7b1cSBarry Smith   See `SNESSetTolerances()` for details on the parameters.
40030b4b7b1cSBarry Smith 
4004dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
4005dc4c0fb0SBarry Smith 
40061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
400733174efeSLois Curfman McInnes @*/
4008d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
4009d71ae5a4SJacob Faibussowitsch {
40103a40ed3dSBarry Smith   PetscFunctionBegin;
40110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
401285385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
401333174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
4014c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
401533174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
401633174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
40173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
401833174efeSLois Curfman McInnes }
401933174efeSLois Curfman McInnes 
4020e4d06f11SPatrick Farrell /*@
4021e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4022e4d06f11SPatrick Farrell 
4023e4d06f11SPatrick Farrell   Not Collective
4024e4d06f11SPatrick Farrell 
4025e4d06f11SPatrick Farrell   Input Parameters:
4026f6dfbefdSBarry Smith + snes   - the `SNES` context
4027e4d06f11SPatrick Farrell - divtol - divergence tolerance
4028e4d06f11SPatrick Farrell 
4029e4d06f11SPatrick Farrell   Level: intermediate
4030e4d06f11SPatrick Farrell 
40311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4032e4d06f11SPatrick Farrell @*/
4033d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4034d71ae5a4SJacob Faibussowitsch {
4035e4d06f11SPatrick Farrell   PetscFunctionBegin;
4036e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4037e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
40383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4039e4d06f11SPatrick Farrell }
4040e4d06f11SPatrick Farrell 
40416ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40426ba87a44SLisandro Dalcin 
4043d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4044d71ae5a4SJacob Faibussowitsch {
4045b271bb04SBarry Smith   PetscDrawLG      lg;
4046b271bb04SBarry Smith   PetscReal        x, y, per;
4047b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4048b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4049b271bb04SBarry Smith   PetscDraw        draw;
4050b271bb04SBarry Smith 
4051459f5d12SBarry Smith   PetscFunctionBegin;
40524d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40539566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40549566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40559566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40569566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4057b271bb04SBarry Smith   x = (PetscReal)n;
405877b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
405994c9c6d3SKarl Rupp   else y = -15.0;
40609566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40616934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40629566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40639566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4064b271bb04SBarry Smith   }
4065b271bb04SBarry Smith 
40669566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
40679566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40689566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4069aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
40709566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4071b271bb04SBarry Smith   x = (PetscReal)n;
4072b271bb04SBarry Smith   y = 100.0 * per;
40739566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40746934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40759566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40769566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4077b271bb04SBarry Smith   }
4078b271bb04SBarry Smith 
40799566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
40809371c9d4SSatish Balay   if (!n) {
40819371c9d4SSatish Balay     prev = rnorm;
40829371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
40839371c9d4SSatish Balay   }
40849566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40859566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4086b271bb04SBarry Smith   x = (PetscReal)n;
4087b271bb04SBarry Smith   y = (prev - rnorm) / prev;
40889566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40896934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40909566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40919566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4092b271bb04SBarry Smith   }
4093b271bb04SBarry Smith 
40949566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
40959566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40969566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40979566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4098b271bb04SBarry Smith   x = (PetscReal)n;
4099b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4100b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
41019566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4102b271bb04SBarry Smith   }
41036934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41049566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41059566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4106b271bb04SBarry Smith   }
4107b271bb04SBarry Smith   prev = rnorm;
41083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4109b271bb04SBarry Smith }
4110b271bb04SBarry Smith 
4111228d79bcSJed Brown /*@
41122d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41132d157150SStefano Zampini 
41142d157150SStefano Zampini   Collective
41152d157150SStefano Zampini 
41162d157150SStefano Zampini   Input Parameters:
41172d157150SStefano Zampini + snes  - the `SNES` context
41182d157150SStefano Zampini . it    - current iteration
41192d157150SStefano Zampini . xnorm - 2-norm of current iterate
41202d157150SStefano Zampini . snorm - 2-norm of current step
41212d157150SStefano Zampini - fnorm - 2-norm of function
41222d157150SStefano Zampini 
41232d157150SStefano Zampini   Level: developer
41242d157150SStefano Zampini 
41252d157150SStefano Zampini   Note:
4126420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41272d157150SStefano Zampini   It does not typically need to be called by the user.
41282d157150SStefano Zampini 
4129c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
41302d157150SStefano Zampini @*/
41312d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41322d157150SStefano Zampini {
41332d157150SStefano Zampini   PetscFunctionBegin;
41342d157150SStefano Zampini   if (!snes->reason) {
41352d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41362d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41372d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41382d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41392d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41402d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41412d157150SStefano Zampini     }
41422d157150SStefano Zampini   }
41432d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41442d157150SStefano Zampini }
41452d157150SStefano Zampini 
41462d157150SStefano Zampini /*@
41470b4b7b1cSBarry Smith   SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database
4148228d79bcSJed Brown 
4149c3339decSBarry Smith   Collective
4150228d79bcSJed Brown 
4151228d79bcSJed Brown   Input Parameters:
4152f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
41530b4b7b1cSBarry Smith . iter  - current iteration number
41540b4b7b1cSBarry Smith - rnorm - current relative norm of the residual
4155228d79bcSJed Brown 
4156dc4c0fb0SBarry Smith   Level: developer
4157dc4c0fb0SBarry Smith 
4158f6dfbefdSBarry Smith   Note:
4159420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4160228d79bcSJed Brown   It does not typically need to be called by the user.
4161228d79bcSJed Brown 
41621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4163228d79bcSJed Brown @*/
4164d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4165d71ae5a4SJacob Faibussowitsch {
41667a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
41677a03ce2fSLisandro Dalcin 
41687a03ce2fSLisandro Dalcin   PetscFunctionBegin;
41695f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
41709566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
417148a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
41729566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
41733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41747a03ce2fSLisandro Dalcin }
41757a03ce2fSLisandro Dalcin 
41769b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
41779b94acceSBarry Smith 
4178bf388a1fSBarry Smith /*MC
4179f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4180bf388a1fSBarry Smith 
4181bf388a1fSBarry Smith      Synopsis:
4182aaa7dc30SBarry Smith      #include <petscsnes.h>
418337fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4184bf388a1fSBarry Smith 
4185c3339decSBarry Smith      Collective
41861843f636SBarry Smith 
41871843f636SBarry Smith     Input Parameters:
4188f6dfbefdSBarry Smith +    snes - the `SNES` context
4189bf388a1fSBarry Smith .    its - iteration number
4190bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4191bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4192bf388a1fSBarry Smith 
4193878cb397SSatish Balay    Level: advanced
4194878cb397SSatish Balay 
41951cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4196bf388a1fSBarry Smith M*/
4197bf388a1fSBarry Smith 
41989b94acceSBarry Smith /*@C
4199a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
42000b4b7b1cSBarry Smith   iteration of the `SNES` nonlinear solver to display the iteration's
42019b94acceSBarry Smith   progress.
42029b94acceSBarry Smith 
4203c3339decSBarry Smith   Logically Collective
4204fee21e36SBarry Smith 
4205c7afd0dbSLois Curfman McInnes   Input Parameters:
4206f6dfbefdSBarry Smith + snes           - the `SNES` context
420720f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4208420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
420949abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
42109b94acceSBarry Smith 
42119665c990SLois Curfman McInnes   Options Database Keys:
4212f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4213798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4214dc4c0fb0SBarry 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
4215c7afd0dbSLois Curfman McInnes                                 the options database.
42169665c990SLois Curfman McInnes 
4217dc4c0fb0SBarry Smith   Level: intermediate
4218dc4c0fb0SBarry Smith 
4219f6dfbefdSBarry Smith   Note:
42206bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4221f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42226bc08f3fSLois Curfman McInnes   order in which they were set.
4223639f9d9dSBarry Smith 
4224420bcc1bSBarry Smith   Fortran Note:
4225f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4226025f1a04SBarry Smith 
422749abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
42289b94acceSBarry Smith @*/
422949abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
4230d71ae5a4SJacob Faibussowitsch {
4231b90d0a6eSBarry Smith   PetscInt  i;
423278064530SBarry Smith   PetscBool identical;
4233b90d0a6eSBarry Smith 
42343a40ed3dSBarry Smith   PetscFunctionBegin;
42350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4236b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
42379566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42383ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4239649052a6SBarry Smith   }
42405f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42416e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4242b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4243835f2295SStefano Zampini   snes->monitorcontext[snes->numbermonitors++] = mctx;
42443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42459b94acceSBarry Smith }
42469b94acceSBarry Smith 
4247a278d85bSSatish Balay /*@
4248f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42495cd90555SBarry Smith 
4250c3339decSBarry Smith   Logically Collective
4251c7afd0dbSLois Curfman McInnes 
42522fe279fdSBarry Smith   Input Parameter:
4253f6dfbefdSBarry Smith . snes - the `SNES` context
42545cd90555SBarry Smith 
42551a480d89SAdministrator   Options Database Key:
4256a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4257dc4c0fb0SBarry Smith                          into a code by calls to `SNESMonitorSet()`, but does not cancel those
4258c7afd0dbSLois Curfman McInnes                          set via the options database
42595cd90555SBarry Smith 
4260dc4c0fb0SBarry Smith   Level: intermediate
4261dc4c0fb0SBarry Smith 
4262f6dfbefdSBarry Smith   Note:
4263f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
42645cd90555SBarry Smith 
42651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
42665cd90555SBarry Smith @*/
4267d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4268d71ae5a4SJacob Faibussowitsch {
4269d952e501SBarry Smith   PetscInt i;
4270d952e501SBarry Smith 
42715cd90555SBarry Smith   PetscFunctionBegin;
42720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4273d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
427448a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4275d952e501SBarry Smith   }
42765cd90555SBarry Smith   snes->numbermonitors = 0;
42773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42785cd90555SBarry Smith }
42795cd90555SBarry Smith 
4280bf388a1fSBarry Smith /*MC
4281bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4282bf388a1fSBarry Smith 
4283bf388a1fSBarry Smith      Synopsis:
4284aaa7dc30SBarry Smith      #include <petscsnes.h>
428537fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4286bf388a1fSBarry Smith 
4287c3339decSBarry Smith      Collective
42881843f636SBarry Smith 
42891843f636SBarry Smith     Input Parameters:
4290f6dfbefdSBarry Smith +    snes - the `SNES` context
4291bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4292bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4293bf388a1fSBarry Smith .    gnorm - 2-norm of current step
42941843f636SBarry Smith .    f - 2-norm of function
42951843f636SBarry Smith -    cctx - [optional] convergence context
42961843f636SBarry Smith 
42971843f636SBarry Smith     Output Parameter:
42981843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4299bf388a1fSBarry Smith 
4300878cb397SSatish Balay    Level: intermediate
4301bf388a1fSBarry Smith 
4302c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
4303bf388a1fSBarry Smith M*/
4304bf388a1fSBarry Smith 
43059b94acceSBarry Smith /*@C
43069b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
43079b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
43089b94acceSBarry Smith 
4309c3339decSBarry Smith   Logically Collective
4310fee21e36SBarry Smith 
4311c7afd0dbSLois Curfman McInnes   Input Parameters:
4312f6dfbefdSBarry Smith + snes                        - the `SNES` context
4313e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4314dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4315dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43169b94acceSBarry Smith 
431736851e7fSLois Curfman McInnes   Level: advanced
431836851e7fSLois Curfman McInnes 
43191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43209b94acceSBarry Smith @*/
4321d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4322d71ae5a4SJacob Faibussowitsch {
43233a40ed3dSBarry Smith   PetscFunctionBegin;
43240700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4325e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
43261baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4327bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43287f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
432985385478SLisandro Dalcin   snes->cnvP                  = cctx;
43303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43319b94acceSBarry Smith }
43329b94acceSBarry Smith 
433352baeb72SSatish Balay /*@
43340b4b7b1cSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4335184914b5SBarry Smith 
4336184914b5SBarry Smith   Not Collective
4337184914b5SBarry Smith 
4338184914b5SBarry Smith   Input Parameter:
4339f6dfbefdSBarry Smith . snes - the `SNES` context
4340184914b5SBarry Smith 
4341184914b5SBarry Smith   Output Parameter:
4342f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4343184914b5SBarry Smith 
4344f6dfbefdSBarry Smith   Options Database Key:
43456a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43466a4d7782SBarry Smith 
4347184914b5SBarry Smith   Level: intermediate
4348184914b5SBarry Smith 
4349f6dfbefdSBarry Smith   Note:
4350f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4351184914b5SBarry Smith 
43521cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4353184914b5SBarry Smith @*/
4354d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4355d71ae5a4SJacob Faibussowitsch {
4356184914b5SBarry Smith   PetscFunctionBegin;
43570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43584f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4359184914b5SBarry Smith   *reason = snes->reason;
43603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4361184914b5SBarry Smith }
4362184914b5SBarry Smith 
4363c4421ceaSFande Kong /*@C
4364f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4365c4421ceaSFande Kong 
4366c4421ceaSFande Kong   Not Collective
4367c4421ceaSFande Kong 
4368c4421ceaSFande Kong   Input Parameter:
4369f6dfbefdSBarry Smith . snes - the `SNES` context
4370c4421ceaSFande Kong 
4371c4421ceaSFande Kong   Output Parameter:
4372dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4373c4421ceaSFande Kong 
437499c90e12SSatish Balay   Level: beginner
4375c4421ceaSFande Kong 
43761cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4377c4421ceaSFande Kong @*/
4378d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4379d71ae5a4SJacob Faibussowitsch {
4380c4421ceaSFande Kong   PetscFunctionBegin;
4381c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43824f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4383c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
43843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4385c4421ceaSFande Kong }
4386c4421ceaSFande Kong 
438733866048SMatthew G. Knepley /*@
4388f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
438933866048SMatthew G. Knepley 
439033866048SMatthew G. Knepley   Not Collective
439133866048SMatthew G. Knepley 
439233866048SMatthew G. Knepley   Input Parameters:
4393f6dfbefdSBarry Smith + snes   - the `SNES` context
4394f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
439533866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
439633866048SMatthew G. Knepley 
4397f6dfbefdSBarry Smith   Level: developer
4398f6dfbefdSBarry Smith 
4399420bcc1bSBarry Smith   Developer Note:
4400f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
440133866048SMatthew G. Knepley 
44021cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
440333866048SMatthew G. Knepley @*/
4404d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4405d71ae5a4SJacob Faibussowitsch {
440633866048SMatthew G. Knepley   PetscFunctionBegin;
440733866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44085f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
440933866048SMatthew G. Knepley   snes->reason = reason;
44103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
441133866048SMatthew G. Knepley }
441233866048SMatthew G. Knepley 
4413c9005455SLois Curfman McInnes /*@
4414420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4415c9005455SLois Curfman McInnes 
4416c3339decSBarry Smith   Logically Collective
4417fee21e36SBarry Smith 
4418c7afd0dbSLois Curfman McInnes   Input Parameters:
4419f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44208c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4421cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4422420bcc1bSBarry Smith . na    - size of `a` and `its`
4423f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4424758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4425c7afd0dbSLois Curfman McInnes 
4426dc4c0fb0SBarry Smith   Level: intermediate
4427dc4c0fb0SBarry Smith 
4428308dcc3eSBarry Smith   Notes:
4429ce78bad3SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` (or, deprecated, `PETSC_DEFAULT`) then a
443077e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4431308dcc3eSBarry Smith 
4432c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4433c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4434c9005455SLois Curfman McInnes   during the section of code that is being timed.
4435c9005455SLois Curfman McInnes 
4436420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4437420bcc1bSBarry Smith 
44381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4439c9005455SLois Curfman McInnes @*/
4440d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4441d71ae5a4SJacob Faibussowitsch {
44423a40ed3dSBarry Smith   PetscFunctionBegin;
44430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44444f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44454f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44467a1ec6d4SBarry Smith   if (!a) {
444777e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44489566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4449071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4450308dcc3eSBarry Smith   }
4451c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4452758f92a0SBarry Smith   snes->conv_hist_its   = its;
4453115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4454a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4455758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4457758f92a0SBarry Smith }
4458758f92a0SBarry Smith 
4459d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4460c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4461c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
446299e0435eSBarry Smith 
4463d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4464d71ae5a4SJacob Faibussowitsch {
4465308dcc3eSBarry Smith   mxArray   *mat;
4466308dcc3eSBarry Smith   PetscInt   i;
4467308dcc3eSBarry Smith   PetscReal *ar;
4468308dcc3eSBarry Smith 
4469308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4470308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4471f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
447211cc89d2SBarry Smith   return mat;
4473308dcc3eSBarry Smith }
4474308dcc3eSBarry Smith #endif
4475308dcc3eSBarry Smith 
44760c4c9dddSBarry Smith /*@C
4477420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4478758f92a0SBarry Smith 
44793f9fe445SBarry Smith   Not Collective
4480758f92a0SBarry Smith 
4481758f92a0SBarry Smith   Input Parameter:
4482f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4483758f92a0SBarry Smith 
4484758f92a0SBarry Smith   Output Parameters:
4485f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4486758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4487758f92a0SBarry Smith          negative if not converged) for each solve.
448820f4b53cSBarry Smith - na  - size of `a` and `its`
4489758f92a0SBarry Smith 
4490dc4c0fb0SBarry Smith   Level: intermediate
4491dc4c0fb0SBarry Smith 
449220f4b53cSBarry Smith   Note:
449320f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
449420f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
449520f4b53cSBarry Smith   during the section of code that is being timed.
449620f4b53cSBarry Smith 
4497ce78bad3SBarry Smith   Fortran Notes:
4498ce78bad3SBarry Smith   Return the arrays with ``SNESRestoreConvergenceHistory()`
4499ce78bad3SBarry Smith 
4500ce78bad3SBarry Smith   Use the arguments
4501dc4c0fb0SBarry Smith .vb
4502ce78bad3SBarry Smith   PetscReal, pointer :: a(:)
4503ce78bad3SBarry Smith   PetscInt, pointer :: its(:)
4504dc4c0fb0SBarry Smith .ve
4505758f92a0SBarry Smith 
45061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4507758f92a0SBarry Smith @*/
4508d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4509d71ae5a4SJacob Faibussowitsch {
4510758f92a0SBarry Smith   PetscFunctionBegin;
45110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4512758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4513758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4514115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
45153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4516c9005455SLois Curfman McInnes }
4517c9005455SLois Curfman McInnes 
4518ac226902SBarry Smith /*@C
451976b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4520eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
452153e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
452253e5d35bSStefano Zampini   evaluation.
452376b2cf59SMatthew Knepley 
4524c3339decSBarry Smith   Logically Collective
452576b2cf59SMatthew Knepley 
452676b2cf59SMatthew Knepley   Input Parameters:
4527a2b725a8SWilliam Gropp + snes - The nonlinear solver context
452853e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
452976b2cf59SMatthew Knepley 
4530fe97e370SBarry Smith   Level: advanced
4531fe97e370SBarry Smith 
4532420bcc1bSBarry Smith   Notes:
4533f6dfbefdSBarry 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
4534f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
453553e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
453653e5d35bSStefano Zampini   right before the direction step is computed.
4537ce78bad3SBarry Smith 
453853e5d35bSStefano Zampini   Users are free to modify the current residual vector,
453953e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
454053e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
4541ce78bad3SBarry Smith   vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like
4542ce78bad3SBarry Smith .vb
4543ce78bad3SBarry Smith   PetscErrorCode update(SNES snes, PetscInt iteration)
4544ce78bad3SBarry Smith   {
4545ce78bad3SBarry Smith     PetscFunctionBeginUser;
4546ce78bad3SBarry Smith     if (iteration > 0) {
4547ce78bad3SBarry Smith       // update the model parameters here
4548ce78bad3SBarry Smith       Vec x,f;
4549ce78bad3SBarry Smith       PetscCall(SNESGetSolution(snes,&x));
4550ce78bad3SBarry Smith       PetcCall(SNESGetFunction(snes,&f,NULL,NULL));
4551ce78bad3SBarry Smith       PetscCall(SNESComputeFunction(snes,x,f));
4552ce78bad3SBarry Smith     }
4553ce78bad3SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
4554ce78bad3SBarry Smith   }
4555ce78bad3SBarry Smith .ve
455676b2cf59SMatthew Knepley 
4557aaa8cc7dSPierre 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.
45586b7fb656SBarry Smith 
4559e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
456053e5d35bSStefano Zampini          `SNESMonitorSet()`
456176b2cf59SMatthew Knepley @*/
456253e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4563d71ae5a4SJacob Faibussowitsch {
456476b2cf59SMatthew Knepley   PetscFunctionBegin;
45650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4566e7788613SBarry Smith   snes->ops->update = func;
45673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
456876b2cf59SMatthew Knepley }
456976b2cf59SMatthew Knepley 
4570ffeef943SBarry Smith /*@
4571f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
45722a359c20SBarry Smith 
4573c3339decSBarry Smith   Collective
45742a359c20SBarry Smith 
4575e4094ef1SJacob Faibussowitsch   Input Parameters:
4576f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
45772a359c20SBarry Smith - viewer - the viewer to display the reason
45782a359c20SBarry Smith 
45792a359c20SBarry Smith   Options Database Keys:
4580ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4581ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4582eafd5ff0SAlex Lindsay 
4583420bcc1bSBarry Smith   Level: beginner
4584420bcc1bSBarry Smith 
4585f6dfbefdSBarry Smith   Note:
4586f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4587f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
45882a359c20SBarry Smith 
45891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4590f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4591f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4592db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
45932a359c20SBarry Smith @*/
4594d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4595d71ae5a4SJacob Faibussowitsch {
459675cca76cSMatthew G. Knepley   PetscViewerFormat format;
45972a359c20SBarry Smith   PetscBool         isAscii;
45982a359c20SBarry Smith 
45992a359c20SBarry Smith   PetscFunctionBegin;
460019a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
46019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
46022a359c20SBarry Smith   if (isAscii) {
46039566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
460465bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
460575cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
460675cca76cSMatthew G. Knepley       DM       dm;
460775cca76cSMatthew G. Knepley       Vec      u;
460875cca76cSMatthew G. Knepley       PetscDS  prob;
460975cca76cSMatthew G. Knepley       PetscInt Nf, f;
461095cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
461195cbbfd3SMatthew G. Knepley       void    **exactCtx;
461275cca76cSMatthew G. Knepley       PetscReal error;
461375cca76cSMatthew G. Knepley 
46149566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
46159566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
46169566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
46179566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
46189566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
46199566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
46209566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
46219566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
46229566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
462363a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
462475cca76cSMatthew G. Knepley     }
4625eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
46262a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
462763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46282a359c20SBarry Smith       } else {
462963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46302a359c20SBarry Smith       }
4631eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
46322a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
463363a3b9bcSJacob 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));
46342a359c20SBarry Smith       } else {
463563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46362a359c20SBarry Smith       }
46372a359c20SBarry Smith     }
463865bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46392a359c20SBarry Smith   }
46403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46412a359c20SBarry Smith }
46422a359c20SBarry Smith 
4643c4421ceaSFande Kong /*@C
4644c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4645aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4646c4421ceaSFande Kong 
4647c3339decSBarry Smith   Logically Collective
4648c4421ceaSFande Kong 
4649c4421ceaSFande Kong   Input Parameters:
4650f6dfbefdSBarry Smith + snes              - the `SNES` context
4651420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4652420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
465349abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4654420bcc1bSBarry Smith 
4655420bcc1bSBarry Smith   Calling sequence of `f`:
4656420bcc1bSBarry Smith + snes - the `SNES` context
465749abdd8aSBarry Smith - vctx - [optional] context for private data for the function
4658c4421ceaSFande Kong 
4659c4421ceaSFande Kong   Options Database Keys:
4660f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4661420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4662420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4663c4421ceaSFande Kong 
4664dc4c0fb0SBarry Smith   Level: intermediate
4665dc4c0fb0SBarry Smith 
4666f6dfbefdSBarry Smith   Note:
4667c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4668f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4669c4421ceaSFande Kong   order in which they were set.
4670c4421ceaSFande Kong 
467149abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
467249abdd8aSBarry Smith           `PetscCtxDestroyFn`
4673c4421ceaSFande Kong @*/
467449abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4675d71ae5a4SJacob Faibussowitsch {
4676c4421ceaSFande Kong   PetscInt  i;
4677c4421ceaSFande Kong   PetscBool identical;
4678c4421ceaSFande Kong 
4679c4421ceaSFande Kong   PetscFunctionBegin;
4680c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4681c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
46829566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
46833ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4684c4421ceaSFande Kong   }
46855f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4686c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4687c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4688835f2295SStefano Zampini   snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
46893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4690c4421ceaSFande Kong }
4691c4421ceaSFande Kong 
469291f3e32bSBarry Smith /*@
4693420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
46940b4b7b1cSBarry Smith   All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
46952a359c20SBarry Smith 
4696c3339decSBarry Smith   Collective
46972a359c20SBarry Smith 
46982fe279fdSBarry Smith   Input Parameter:
4699f6dfbefdSBarry Smith . snes - the `SNES` object
47002a359c20SBarry Smith 
4701f6dfbefdSBarry Smith   Level: advanced
47022a359c20SBarry Smith 
47031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4704f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
47052a359c20SBarry Smith @*/
4706d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4707d71ae5a4SJacob Faibussowitsch {
47082a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
47092a359c20SBarry Smith 
47102a359c20SBarry Smith   PetscFunctionBegin;
47113ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
47122a359c20SBarry Smith   incall = PETSC_TRUE;
4713c4421ceaSFande Kong 
4714c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
471536d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4716c4421ceaSFande Kong 
4717c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
471836d43d94SBarry Smith   if (snes->convergedreasonviewer) {
471936d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
472036d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
472136d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
47222a359c20SBarry Smith   }
47232a359c20SBarry Smith   incall = PETSC_FALSE;
47243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47252a359c20SBarry Smith }
47262a359c20SBarry Smith 
4727487a658cSBarry Smith /*@
47280b4b7b1cSBarry Smith   SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
47299b94acceSBarry Smith 
4730c3339decSBarry Smith   Collective
4731c7afd0dbSLois Curfman McInnes 
4732b2002411SLois Curfman McInnes   Input Parameters:
4733f6dfbefdSBarry Smith + snes - the `SNES` context
47340b4b7b1cSBarry Smith . b    - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
473585385478SLisandro Dalcin - x    - the solution vector.
47369b94acceSBarry Smith 
4737dc4c0fb0SBarry Smith   Level: beginner
4738dc4c0fb0SBarry Smith 
4739f6dfbefdSBarry Smith   Note:
4740420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4741a9b45538SStefano Zampini   for the nonlinear solve prior to calling `SNESSolve()` .
47428ddd3da0SLois Curfman McInnes 
47431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4744db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4745a9b45538SStefano Zampini           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
47469b94acceSBarry Smith @*/
4747d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4748d71ae5a4SJacob Faibussowitsch {
4749ace3abfcSBarry Smith   PetscBool flg;
4750efd51863SBarry Smith   PetscInt  grid;
47510298fd71SBarry Smith   Vec       xcreated = NULL;
4752caa4e7f2SJed Brown   DM        dm;
4753052efed2SBarry Smith 
47543a40ed3dSBarry Smith   PetscFunctionBegin;
47550700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4756a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4757a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47580700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
475985385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
476085385478SLisandro Dalcin 
476134b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
476206fc46c8SMatthew G. Knepley   {
476306fc46c8SMatthew G. Knepley     PetscViewer       viewer;
476406fc46c8SMatthew G. Knepley     PetscViewerFormat format;
47657c88af5aSMatthew G. Knepley     PetscInt          num;
476606fc46c8SMatthew G. Knepley     PetscBool         flg;
476706fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
476806fc46c8SMatthew G. Knepley 
476906fc46c8SMatthew G. Knepley     if (!incall) {
477034b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4771648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
477206fc46c8SMatthew G. Knepley       if (flg) {
477306fc46c8SMatthew G. Knepley         PetscConvEst conv;
477446079b62SMatthew G. Knepley         DM           dm;
477546079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
477646079b62SMatthew G. Knepley         PetscInt     Nf;
477706fc46c8SMatthew G. Knepley 
477806fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
47799566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
47809566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
47819566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
47829566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
47839566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
47849566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
47859566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
47869566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
47879566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
47889566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
47899566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4790648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
47919566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
47929566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
479306fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
479406fc46c8SMatthew G. Knepley       }
479534b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4796b2588ea6SMatthew G. Knepley       num = 1;
47979566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
479834b4d3a8SMatthew G. Knepley       if (flg) {
479934b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
480034b4d3a8SMatthew G. Knepley 
480134b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
48029566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
48039566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48049566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48069566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
48079566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
48089566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
480934b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
481034b4d3a8SMatthew G. Knepley       }
48117c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
48127c88af5aSMatthew G. Knepley       num = 0;
48139566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
48147c88af5aSMatthew G. Knepley       if (num) {
48157c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4816e03fd340SMatthew G. Knepley         const char *prefix;
48177c88af5aSMatthew G. Knepley 
48187c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
48199566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4820e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4821e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
48229566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48239566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48249566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48259566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4826e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48279566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48289566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
48297c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
48307c88af5aSMatthew G. Knepley       }
483106fc46c8SMatthew G. Knepley     }
483206fc46c8SMatthew G. Knepley   }
4833ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4834caa4e7f2SJed Brown   if (!x) {
48359566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48369566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4837a69afd8bSBarry Smith     x = xcreated;
4838a69afd8bSBarry Smith   }
48399566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4840f05ece33SBarry Smith 
48419566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4842efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
484385385478SLisandro Dalcin     /* set solution vector */
48449566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48459566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
484685385478SLisandro Dalcin     snes->vec_sol = x;
48479566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4848caa4e7f2SJed Brown 
4849caa4e7f2SJed Brown     /* set affine vector if provided */
48509566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48519566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
485285385478SLisandro Dalcin     snes->vec_rhs = b;
485385385478SLisandro Dalcin 
48545f80ce2aSJacob 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");
48555f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4856dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4857aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48589566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48599566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48603f149594SLisandro Dalcin 
48617eee914bSBarry Smith     if (!grid) {
48629927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4863dd568438SSatish Balay     }
4864d25893d9SBarry Smith 
4865abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
486612b1dd1aSStefano Zampini     PetscCall(SNESResetCounters(snes));
48672d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
48689566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4869dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
48709566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
48712d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4872422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
48733f149594SLisandro Dalcin 
487437ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
487537ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
487637ec4e1aSPeter Brune 
4877648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
48789566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4879c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
48809566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
48815968eb51SBarry Smith 
48825f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
48839c8e83a9SBarry Smith     if (snes->reason < 0) break;
4884efd51863SBarry Smith     if (grid < snes->gridsequence) {
4885efd51863SBarry Smith       DM  fine;
4886efd51863SBarry Smith       Vec xnew;
4887efd51863SBarry Smith       Mat interp;
4888efd51863SBarry Smith 
48899566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
48905f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
48912eace19aSMatthew G. Knepley       PetscCall(DMGetCoordinatesLocalSetUp(fine));
48929566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
48939566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
48949566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
48959566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
48969566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4897efd51863SBarry Smith       x = xnew;
4898efd51863SBarry Smith 
48999566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
49009566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
49019566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
49029566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
49039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4904efd51863SBarry Smith     }
4905efd51863SBarry Smith   }
49069566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
49079566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
49089566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
49099566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
49103f7e2da0SPeter Brune 
49119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
49129566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
49133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49149b94acceSBarry Smith }
49159b94acceSBarry Smith 
49169b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
49179b94acceSBarry Smith 
4918cc4c1da9SBarry Smith /*@
49190b4b7b1cSBarry Smith   SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES`
49209b94acceSBarry Smith 
4921c3339decSBarry Smith   Collective
4922fee21e36SBarry Smith 
4923c7afd0dbSLois Curfman McInnes   Input Parameters:
4924f6dfbefdSBarry Smith + snes - the `SNES` context
4925454a90a3SBarry Smith - type - a known method
4926c7afd0dbSLois Curfman McInnes 
4927c7afd0dbSLois Curfman McInnes   Options Database Key:
4928454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
492904d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4930ae12b187SLois Curfman McInnes 
4931dc4c0fb0SBarry Smith   Level: intermediate
4932dc4c0fb0SBarry Smith 
49339b94acceSBarry Smith   Notes:
49340b4b7b1cSBarry Smith   See `SNESType` for available methods (for instance)
4935f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4936c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49374a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4938c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49399b94acceSBarry Smith 
4940f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4941f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4942ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4943ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4944f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4945ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4946ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4947ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4948ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4949b0a32e0cSBarry Smith   appropriate method.
495036851e7fSLois Curfman McInnes 
4951420bcc1bSBarry Smith   Developer Note:
4952f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4953f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
49548f6c3df8SBarry Smith 
49551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49569b94acceSBarry Smith @*/
4957d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4958d71ae5a4SJacob Faibussowitsch {
4959ace3abfcSBarry Smith   PetscBool match;
49605f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
49613a40ed3dSBarry Smith 
49623a40ed3dSBarry Smith   PetscFunctionBegin;
49630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49644f572ea9SToby Isaac   PetscAssertPointer(type, 2);
496582bf6240SBarry Smith 
49669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
49673ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
496892ff6ae8SBarry Smith 
49699566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
49706adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
497175396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4972dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
497343547594SStefano Zampini   /* Reinitialize type-specific function pointers in SNESOps structure */
497443547594SStefano Zampini   snes->ops->reset          = NULL;
49759e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
49769e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
49779e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
49789e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
49799e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
49807fe760d5SStefano Zampini 
49817fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
49829566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
49837fe760d5SStefano Zampini 
498475396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
498575396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4986f5af7f23SKarl Rupp 
49879566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
49889566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
49893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49909b94acceSBarry Smith }
49919b94acceSBarry Smith 
4992cc4c1da9SBarry Smith /*@
4993f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
49949b94acceSBarry Smith 
4995c7afd0dbSLois Curfman McInnes   Not Collective
4996c7afd0dbSLois Curfman McInnes 
49979b94acceSBarry Smith   Input Parameter:
49984b0e389bSBarry Smith . snes - nonlinear solver context
49999b94acceSBarry Smith 
50009b94acceSBarry Smith   Output Parameter:
5001f6dfbefdSBarry Smith . type - `SNES` method (a character string)
50029b94acceSBarry Smith 
500336851e7fSLois Curfman McInnes   Level: intermediate
500436851e7fSLois Curfman McInnes 
50051cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
50069b94acceSBarry Smith @*/
5007d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
5008d71ae5a4SJacob Faibussowitsch {
50093a40ed3dSBarry Smith   PetscFunctionBegin;
50100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50114f572ea9SToby Isaac   PetscAssertPointer(type, 2);
50127adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
50133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50149b94acceSBarry Smith }
50159b94acceSBarry Smith 
50163cd8a7caSMatthew G. Knepley /*@
5017f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
50183cd8a7caSMatthew G. Knepley 
5019c3339decSBarry Smith   Logically Collective
50203cd8a7caSMatthew G. Knepley 
50213cd8a7caSMatthew G. Knepley   Input Parameters:
5022f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
50233cd8a7caSMatthew G. Knepley - u    - the solution vector
50243cd8a7caSMatthew G. Knepley 
50253cd8a7caSMatthew G. Knepley   Level: beginner
50263cd8a7caSMatthew G. Knepley 
50271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
50283cd8a7caSMatthew G. Knepley @*/
5029d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5030d71ae5a4SJacob Faibussowitsch {
50313cd8a7caSMatthew G. Knepley   DM dm;
50323cd8a7caSMatthew G. Knepley 
50333cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
50343cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50353cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
50379566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
50383cd8a7caSMatthew G. Knepley 
50393cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
50403cd8a7caSMatthew G. Knepley 
50419566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50429566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
50433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50443cd8a7caSMatthew G. Knepley }
50453cd8a7caSMatthew G. Knepley 
504652baeb72SSatish Balay /*@
50479b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
5048f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50499b94acceSBarry Smith 
5050420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5051c7afd0dbSLois Curfman McInnes 
50529b94acceSBarry Smith   Input Parameter:
5053f6dfbefdSBarry Smith . snes - the `SNES` context
50549b94acceSBarry Smith 
50559b94acceSBarry Smith   Output Parameter:
50569b94acceSBarry Smith . x - the solution
50579b94acceSBarry Smith 
505870e92668SMatthew Knepley   Level: intermediate
505936851e7fSLois Curfman McInnes 
50601cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
50619b94acceSBarry Smith @*/
5062d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5063d71ae5a4SJacob Faibussowitsch {
50643a40ed3dSBarry Smith   PetscFunctionBegin;
50650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50664f572ea9SToby Isaac   PetscAssertPointer(x, 2);
506785385478SLisandro Dalcin   *x = snes->vec_sol;
50683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
506970e92668SMatthew Knepley }
507070e92668SMatthew Knepley 
507152baeb72SSatish Balay /*@
50729b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
50739b94acceSBarry Smith   stored.
50749b94acceSBarry Smith 
5075420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5076c7afd0dbSLois Curfman McInnes 
50779b94acceSBarry Smith   Input Parameter:
5078f6dfbefdSBarry Smith . snes - the `SNES` context
50799b94acceSBarry Smith 
50809b94acceSBarry Smith   Output Parameter:
50819b94acceSBarry Smith . x - the solution update
50829b94acceSBarry Smith 
508336851e7fSLois Curfman McInnes   Level: advanced
508436851e7fSLois Curfman McInnes 
50851cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
50869b94acceSBarry Smith @*/
5087d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5088d71ae5a4SJacob Faibussowitsch {
50893a40ed3dSBarry Smith   PetscFunctionBegin;
50900700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50914f572ea9SToby Isaac   PetscAssertPointer(x, 2);
509285385478SLisandro Dalcin   *x = snes->vec_sol_update;
50933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50949b94acceSBarry Smith }
50959b94acceSBarry Smith 
50969b94acceSBarry Smith /*@C
5097f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
50989b94acceSBarry Smith 
5099420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5100c7afd0dbSLois Curfman McInnes 
51019b94acceSBarry Smith   Input Parameter:
5102f6dfbefdSBarry Smith . snes - the `SNES` context
51039b94acceSBarry Smith 
5104d8d19677SJose E. Roman   Output Parameters:
5105dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
51068434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5107dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
51089b94acceSBarry Smith 
510936851e7fSLois Curfman McInnes   Level: advanced
511036851e7fSLois Curfman McInnes 
5111f6dfbefdSBarry Smith   Note:
5112dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
511304edfde5SBarry Smith 
51148434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
51159b94acceSBarry Smith @*/
51168434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5117d71ae5a4SJacob Faibussowitsch {
51186cab3a1bSJed Brown   DM dm;
5119a63bb30eSJed Brown 
51203a40ed3dSBarry Smith   PetscFunctionBegin;
51210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5122a63bb30eSJed Brown   if (r) {
5123a63bb30eSJed Brown     if (!snes->vec_func) {
5124a63bb30eSJed Brown       if (snes->vec_rhs) {
51259566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5126a63bb30eSJed Brown       } else if (snes->vec_sol) {
51279566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5128a63bb30eSJed Brown       } else if (snes->dm) {
51299566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5130a63bb30eSJed Brown       }
5131a63bb30eSJed Brown     }
5132a63bb30eSJed Brown     *r = snes->vec_func;
5133a63bb30eSJed Brown   }
51349566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51359566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
51363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51379b94acceSBarry Smith }
51389b94acceSBarry Smith 
5139c79ef259SPeter Brune /*@C
514037fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5141c79ef259SPeter Brune 
5142c79ef259SPeter Brune   Input Parameter:
5143f6dfbefdSBarry Smith . snes - the `SNES` context
5144c79ef259SPeter Brune 
5145d8d19677SJose E. Roman   Output Parameters:
51468434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5147dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5148c79ef259SPeter Brune 
5149c79ef259SPeter Brune   Level: advanced
5150c79ef259SPeter Brune 
51518434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5152c79ef259SPeter Brune @*/
51538434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5154d71ae5a4SJacob Faibussowitsch {
51556cab3a1bSJed Brown   DM dm;
51566cab3a1bSJed Brown 
5157646217ecSPeter Brune   PetscFunctionBegin;
5158646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51609566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
51613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5162646217ecSPeter Brune }
5163646217ecSPeter Brune 
5164cc4c1da9SBarry Smith /*@
51653c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5166f6dfbefdSBarry Smith   `SNES` options in the database.
51673c7409f5SSatish Balay 
5168c3339decSBarry Smith   Logically Collective
5169fee21e36SBarry Smith 
5170d8d19677SJose E. Roman   Input Parameters:
5171f6dfbefdSBarry Smith + snes   - the `SNES` context
5172c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5173c7afd0dbSLois Curfman McInnes 
5174dc4c0fb0SBarry Smith   Level: advanced
5175dc4c0fb0SBarry Smith 
5176f6dfbefdSBarry Smith   Note:
5177a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5178c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5179d850072dSLois Curfman McInnes 
51801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
51813c7409f5SSatish Balay @*/
5182d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5183d71ae5a4SJacob Faibussowitsch {
51843a40ed3dSBarry Smith   PetscFunctionBegin;
51850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51869566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
51879566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
518835f5d045SPeter Brune   if (snes->linesearch) {
51899566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51909566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
519135f5d045SPeter Brune   }
51929566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
51933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51943c7409f5SSatish Balay }
51953c7409f5SSatish Balay 
5196cc4c1da9SBarry Smith /*@
5197f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5198f6dfbefdSBarry Smith   `SNES` options in the database.
51993c7409f5SSatish Balay 
5200c3339decSBarry Smith   Logically Collective
5201fee21e36SBarry Smith 
5202c7afd0dbSLois Curfman McInnes   Input Parameters:
5203f6dfbefdSBarry Smith + snes   - the `SNES` context
5204c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5205c7afd0dbSLois Curfman McInnes 
5206dc4c0fb0SBarry Smith   Level: advanced
5207dc4c0fb0SBarry Smith 
5208f6dfbefdSBarry Smith   Note:
5209a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5210c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5211d850072dSLois Curfman McInnes 
52121cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
52133c7409f5SSatish Balay @*/
5214d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5215d71ae5a4SJacob Faibussowitsch {
52163a40ed3dSBarry Smith   PetscFunctionBegin;
52170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52189566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
52199566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
522035f5d045SPeter Brune   if (snes->linesearch) {
52219566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52229566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
522335f5d045SPeter Brune   }
52249566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
52253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52263c7409f5SSatish Balay }
52273c7409f5SSatish Balay 
5228cc4c1da9SBarry Smith /*@
5229f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5230f6dfbefdSBarry Smith   `SNES` options in the database.
52313c7409f5SSatish Balay 
5232c7afd0dbSLois Curfman McInnes   Not Collective
5233c7afd0dbSLois Curfman McInnes 
52343c7409f5SSatish Balay   Input Parameter:
5235f6dfbefdSBarry Smith . snes - the `SNES` context
52363c7409f5SSatish Balay 
52373c7409f5SSatish Balay   Output Parameter:
52383c7409f5SSatish Balay . prefix - pointer to the prefix string used
52393c7409f5SSatish Balay 
524036851e7fSLois Curfman McInnes   Level: advanced
524136851e7fSLois Curfman McInnes 
52421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52433c7409f5SSatish Balay @*/
5244d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5245d71ae5a4SJacob Faibussowitsch {
52463a40ed3dSBarry Smith   PetscFunctionBegin;
52470700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52503c7409f5SSatish Balay }
52513c7409f5SSatish Balay 
52523cea93caSBarry Smith /*@C
52531c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
52541c84c290SBarry Smith 
525520f4b53cSBarry Smith   Not Collective
52561c84c290SBarry Smith 
52571c84c290SBarry Smith   Input Parameters:
525820f4b53cSBarry Smith + sname    - name of a new user-defined solver
525920f4b53cSBarry Smith - function - routine to create method context
52601c84c290SBarry Smith 
5261dc4c0fb0SBarry Smith   Level: advanced
5262dc4c0fb0SBarry Smith 
5263f6dfbefdSBarry Smith   Note:
5264f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
52651c84c290SBarry Smith 
5266e4094ef1SJacob Faibussowitsch   Example Usage:
52671c84c290SBarry Smith .vb
5268bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
52691c84c290SBarry Smith .ve
52701c84c290SBarry Smith 
52711c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
5272b44f4de4SBarry Smith .vb
5273b44f4de4SBarry Smith   SNESSetType(snes, "my_solver")
5274b44f4de4SBarry Smith .ve
52751c84c290SBarry Smith   or at runtime via the option
5276b44f4de4SBarry Smith .vb
5277b44f4de4SBarry Smith   -snes_type my_solver
5278b44f4de4SBarry Smith .ve
52791c84c290SBarry Smith 
52801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
52813cea93caSBarry Smith @*/
5282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5283d71ae5a4SJacob Faibussowitsch {
5284b2002411SLois Curfman McInnes   PetscFunctionBegin;
52859566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
52869566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
52873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5288b2002411SLois Curfman McInnes }
5289da9b6338SBarry Smith 
5290d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5291d71ae5a4SJacob Faibussowitsch {
529277431f27SBarry Smith   PetscInt    N, i, j;
5293da9b6338SBarry Smith   Vec         u, uh, fh;
5294da9b6338SBarry Smith   PetscScalar value;
5295da9b6338SBarry Smith   PetscReal   norm;
5296da9b6338SBarry Smith 
5297da9b6338SBarry Smith   PetscFunctionBegin;
52989566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
52999566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
53009566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5301da9b6338SBarry Smith 
5302da9b6338SBarry Smith   /* currently only works for sequential */
53039566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
53049566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5305da9b6338SBarry Smith   for (i = 0; i < N; i++) {
53069566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
530763a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5308da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
53098b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
53109566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
53119566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
53129566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
531363a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5314da9b6338SBarry Smith       value = -value;
53159566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5316da9b6338SBarry Smith     }
5317da9b6338SBarry Smith   }
53189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
53199566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
53203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5321da9b6338SBarry Smith }
532271f87433Sdalcinl 
532371f87433Sdalcinl /*@
5324f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
532571f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
532671f87433Sdalcinl   Newton method.
532771f87433Sdalcinl 
5328c3339decSBarry Smith   Logically Collective
532971f87433Sdalcinl 
533071f87433Sdalcinl   Input Parameters:
5331f6dfbefdSBarry Smith + snes - `SNES` context
5332f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
533371f87433Sdalcinl 
5334f6dfbefdSBarry Smith   Options Database Keys:
533564ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
533664ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
533764ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
533864ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
533964ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
534064ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
534164ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
534264ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
534364ba62caSBarry Smith 
5344dc4c0fb0SBarry Smith   Level: advanced
5345dc4c0fb0SBarry Smith 
5346f6dfbefdSBarry Smith   Note:
5347f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
534871f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
53491d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
535071f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
535171f87433Sdalcinl   solver.
535271f87433Sdalcinl 
53531cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
535471f87433Sdalcinl @*/
5355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5356d71ae5a4SJacob Faibussowitsch {
535771f87433Sdalcinl   PetscFunctionBegin;
53580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5359acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
536071f87433Sdalcinl   snes->ksp_ewconv = flag;
53613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536271f87433Sdalcinl }
536371f87433Sdalcinl 
536471f87433Sdalcinl /*@
5365f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
536671f87433Sdalcinl   for computing relative tolerance for linear solvers within an
536771f87433Sdalcinl   inexact Newton method.
536871f87433Sdalcinl 
536971f87433Sdalcinl   Not Collective
537071f87433Sdalcinl 
537171f87433Sdalcinl   Input Parameter:
5372f6dfbefdSBarry Smith . snes - `SNES` context
537371f87433Sdalcinl 
537471f87433Sdalcinl   Output Parameter:
5375f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
537671f87433Sdalcinl 
537771f87433Sdalcinl   Level: advanced
537871f87433Sdalcinl 
53791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
538071f87433Sdalcinl @*/
5381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5382d71ae5a4SJacob Faibussowitsch {
538371f87433Sdalcinl   PetscFunctionBegin;
53840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
53854f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
538671f87433Sdalcinl   *flag = snes->ksp_ewconv;
53873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
538871f87433Sdalcinl }
538971f87433Sdalcinl 
539071f87433Sdalcinl /*@
5391fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
539271f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
539371f87433Sdalcinl   Newton method.
539471f87433Sdalcinl 
5395c3339decSBarry Smith   Logically Collective
539671f87433Sdalcinl 
539771f87433Sdalcinl   Input Parameters:
5398f6dfbefdSBarry Smith + snes      - `SNES` context
53990f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
540071f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
540171f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
540271f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
540371f87433Sdalcinl              (0 <= gamma2 <= 1)
540471f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
540571f87433Sdalcinl . alpha2    - power for safeguard
540671f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
540771f87433Sdalcinl 
5408dc4c0fb0SBarry Smith   Level: advanced
5409dc4c0fb0SBarry Smith 
5410f6dfbefdSBarry Smith   Notes:
541171f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
541271f87433Sdalcinl 
541377e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
541471f87433Sdalcinl 
54151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
541671f87433Sdalcinl @*/
5417d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5418d71ae5a4SJacob Faibussowitsch {
5419fa9f3622SBarry Smith   SNESKSPEW *kctx;
54205fd66863SKarl Rupp 
542171f87433Sdalcinl   PetscFunctionBegin;
54220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5423fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54245f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5425c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5426c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5427c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5428c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5429c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5430c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5431c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
543271f87433Sdalcinl 
543377e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
543477e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
543577e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
543677e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
543777e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
543877e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
543977e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
544071f87433Sdalcinl 
54410f0abf79SStefano 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);
54420b121fc5SBarry 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);
54430b121fc5SBarry 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);
54440b121fc5SBarry 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);
54450b121fc5SBarry 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);
54460b121fc5SBarry 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);
54473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
544871f87433Sdalcinl }
544971f87433Sdalcinl 
545071f87433Sdalcinl /*@
5451fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
545271f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
545371f87433Sdalcinl   Newton method.
545471f87433Sdalcinl 
545571f87433Sdalcinl   Not Collective
545671f87433Sdalcinl 
545797bb3fdcSJose E. Roman   Input Parameter:
5458f6dfbefdSBarry Smith . snes - `SNES` context
545971f87433Sdalcinl 
546071f87433Sdalcinl   Output Parameters:
54610f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
546271f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
546371f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5464bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
546571f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
546671f87433Sdalcinl . alpha2    - power for safeguard
546771f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
546871f87433Sdalcinl 
546971f87433Sdalcinl   Level: advanced
547071f87433Sdalcinl 
54711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
547271f87433Sdalcinl @*/
5473d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5474d71ae5a4SJacob Faibussowitsch {
5475fa9f3622SBarry Smith   SNESKSPEW *kctx;
54765fd66863SKarl Rupp 
547771f87433Sdalcinl   PetscFunctionBegin;
54780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5479fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54805f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
548171f87433Sdalcinl   if (version) *version = kctx->version;
548271f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
548371f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
548471f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
548571f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
548671f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
548771f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
54883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
548971f87433Sdalcinl }
549071f87433Sdalcinl 
54915c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5492d71ae5a4SJacob Faibussowitsch {
54935c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5494fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
549577e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
549671f87433Sdalcinl 
549771f87433Sdalcinl   PetscFunctionBegin;
54983ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
549930058271SDmitry Karpeev   if (!snes->iter) {
550030058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
55019566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
55020f0abf79SStefano Zampini   } else {
55030fdf79fbSJacob 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);
550471f87433Sdalcinl     if (kctx->version == 1) {
55050f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
550685ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
550771f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
550871f87433Sdalcinl     } else if (kctx->version == 2) {
550985ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
551085ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
551171f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
551271f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
551385ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
551471f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
551585ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
551671f87433Sdalcinl       stol = PetscMax(rtol, stol);
551771f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
551871f87433Sdalcinl       /* safeguard: avoid oversolving */
551930058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
552071f87433Sdalcinl       stol = PetscMax(rtol, stol);
552171f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
55220fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
55230fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
55240f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
55250f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
55260f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
55270f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
55280f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
55290f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
55300f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
55310f0abf79SStefano Zampini 
5532a4598233SStefano 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;
55330f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
55340f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
55350f0abf79SStefano Zampini       kctx->rk_last     = rk;
55360fdf79fbSJacob Faibussowitsch     }
55370f0abf79SStefano Zampini   }
55380f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
553971f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
554077e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
554163a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
55423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
554371f87433Sdalcinl }
554471f87433Sdalcinl 
55455c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5546d71ae5a4SJacob Faibussowitsch {
55475c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5548fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
554971f87433Sdalcinl   PCSide     pcside;
555071f87433Sdalcinl   Vec        lres;
555171f87433Sdalcinl 
555271f87433Sdalcinl   PetscFunctionBegin;
55533ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
55549566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
555571dbe336SPeter Brune   kctx->norm_last = snes->norm;
55560f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
55574f00ce20SMatthew G. Knepley     PC        pc;
55580f0abf79SStefano Zampini     PetscBool getRes;
55594f00ce20SMatthew G. Knepley 
55609566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
55610f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
55620f0abf79SStefano Zampini     if (!getRes) {
55630f0abf79SStefano Zampini       KSPNormType normtype;
55640f0abf79SStefano Zampini 
55650f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
55660f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
55670f0abf79SStefano Zampini     }
55689566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
55690f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
55709566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
557171f87433Sdalcinl     } else {
557271f87433Sdalcinl       /* KSP residual is preconditioned residual */
557371f87433Sdalcinl       /* compute true linear residual norm */
55740f0abf79SStefano Zampini       Mat J;
55750f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
55769566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
55770f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
55789566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
55799566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
55809566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
558171f87433Sdalcinl     }
558271f87433Sdalcinl   }
55833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
558471f87433Sdalcinl }
558571f87433Sdalcinl 
5586d4211eb9SBarry Smith /*@
5587f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5588d4211eb9SBarry Smith 
5589420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5590d4211eb9SBarry Smith 
5591d4211eb9SBarry Smith   Input Parameter:
5592f6dfbefdSBarry Smith . snes - the `SNES` context
5593d4211eb9SBarry Smith 
5594d4211eb9SBarry Smith   Output Parameter:
5595f6dfbefdSBarry Smith . ksp - the `KSP` context
5596d4211eb9SBarry Smith 
5597dc4c0fb0SBarry Smith   Level: beginner
5598dc4c0fb0SBarry Smith 
5599d4211eb9SBarry Smith   Notes:
5600f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5601d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5602f6dfbefdSBarry Smith   `PC` contexts as well.
5603f6dfbefdSBarry Smith 
56040b4b7b1cSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function, changes to that `KSP` will have no effect.
5605d4211eb9SBarry Smith 
56061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5607d4211eb9SBarry Smith @*/
5608d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5609d71ae5a4SJacob Faibussowitsch {
561071f87433Sdalcinl   PetscFunctionBegin;
5611d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56124f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5613d4211eb9SBarry Smith 
5614d4211eb9SBarry Smith   if (!snes->ksp) {
56159566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
56169566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5617d4211eb9SBarry Smith 
56185c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
56195c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5620a5c2985bSBarry Smith 
56219566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
56229566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5623d4211eb9SBarry Smith   }
5624d4211eb9SBarry Smith   *ksp = snes->ksp;
56253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
562671f87433Sdalcinl }
56276c699258SBarry Smith 
5628af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
56296c699258SBarry Smith /*@
56300b4b7b1cSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners
56316c699258SBarry Smith 
5632c3339decSBarry Smith   Logically Collective
56336c699258SBarry Smith 
56346c699258SBarry Smith   Input Parameters:
56352a808120SBarry Smith + snes - the nonlinear solver context
5636420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5637dc4c0fb0SBarry Smith 
5638dc4c0fb0SBarry Smith   Level: intermediate
56396c699258SBarry Smith 
5640f6dfbefdSBarry Smith   Note:
5641f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5642f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5643e03a659cSJed Brown   problems using the same function space.
5644e03a659cSJed Brown 
5645420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
56466c699258SBarry Smith @*/
5647d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5648d71ae5a4SJacob Faibussowitsch {
5649345fed2cSBarry Smith   KSP    ksp;
5650942e3340SBarry Smith   DMSNES sdm;
56516c699258SBarry Smith 
56526c699258SBarry Smith   PetscFunctionBegin;
56530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56542a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
56559566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5656942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
565751f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
56589566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
56599566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5660f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
56616cab3a1bSJed Brown     }
56629566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
56639566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
56646cab3a1bSJed Brown   }
56656c699258SBarry Smith   snes->dm     = dm;
5666116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5667f5af7f23SKarl Rupp 
56689566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
56699566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
56709566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5671efd4aadfSBarry Smith   if (snes->npc) {
56729566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
56739566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
56742c155ee1SBarry Smith   }
56753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56766c699258SBarry Smith }
56776c699258SBarry Smith 
56786c699258SBarry Smith /*@
56790b4b7b1cSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners
56806c699258SBarry Smith 
56810b4b7b1cSBarry Smith   Not Collective but `dm` obtained is parallel on `snes`
56826c699258SBarry Smith 
56836c699258SBarry Smith   Input Parameter:
5684420bcc1bSBarry Smith . snes - the `SNES` context
56856c699258SBarry Smith 
56866c699258SBarry Smith   Output Parameter:
5687420bcc1bSBarry Smith . dm - the `DM`
56886c699258SBarry Smith 
56896c699258SBarry Smith   Level: intermediate
56906c699258SBarry Smith 
5691420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
56926c699258SBarry Smith @*/
5693d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5694d71ae5a4SJacob Faibussowitsch {
56956c699258SBarry Smith   PetscFunctionBegin;
56960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56976cab3a1bSJed Brown   if (!snes->dm) {
56989566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5699116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
57006cab3a1bSJed Brown   }
57016c699258SBarry Smith   *dm = snes->dm;
57023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57036c699258SBarry Smith }
57040807856dSBarry Smith 
570531823bd8SMatthew G Knepley /*@
5706be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
570731823bd8SMatthew G Knepley 
5708c3339decSBarry Smith   Collective
570931823bd8SMatthew G Knepley 
571031823bd8SMatthew G Knepley   Input Parameters:
5711f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
571262842358SBarry Smith - npc  - the `SNES` nonlinear preconditioner object
571362842358SBarry Smith 
571462842358SBarry Smith   Options Database Key:
571562842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
571631823bd8SMatthew G Knepley 
5717dc4c0fb0SBarry Smith   Level: developer
5718dc4c0fb0SBarry Smith 
571931823bd8SMatthew G Knepley   Notes:
572062842358SBarry Smith   This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API.
572131823bd8SMatthew G Knepley 
5722f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5723f6dfbefdSBarry Smith 
5724420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
572531823bd8SMatthew G Knepley @*/
5726d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5727d71ae5a4SJacob Faibussowitsch {
572831823bd8SMatthew G Knepley   PetscFunctionBegin;
572931823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5730f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5731f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5732f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
57339566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5734f6dfbefdSBarry Smith   snes->npc = npc;
57353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
573631823bd8SMatthew G Knepley }
573731823bd8SMatthew G Knepley 
573831823bd8SMatthew G Knepley /*@
5739f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
574031823bd8SMatthew G Knepley 
57410b4b7b1cSBarry Smith   Not Collective; but any changes to the obtained the `pc` object must be applied collectively
574231823bd8SMatthew G Knepley 
574331823bd8SMatthew G Knepley   Input Parameter:
5744f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
574531823bd8SMatthew G Knepley 
574631823bd8SMatthew G Knepley   Output Parameter:
574762842358SBarry Smith . pc - the `SNES` preconditioner context
574831823bd8SMatthew G Knepley 
5749f6dfbefdSBarry Smith   Options Database Key:
5750f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5751b5badacbSBarry Smith 
57520b4b7b1cSBarry Smith   Level: advanced
5753dc4c0fb0SBarry Smith 
575495452b02SPatrick Sanan   Notes:
57550b4b7b1cSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will
57560b4b7b1cSBarry Smith   be used as the nonlinear preconditioner for the current `SNES`.
5757be95d8f1SBarry Smith 
5758f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
575962842358SBarry Smith   `SNES`. These may be overwritten if needed.
576062842358SBarry Smith 
576162842358SBarry Smith   Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner
5762951fe5abSBarry Smith 
57631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
576431823bd8SMatthew G Knepley @*/
5765d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5766d71ae5a4SJacob Faibussowitsch {
5767a64e098fSPeter Brune   const char *optionsprefix;
576831823bd8SMatthew G Knepley 
576931823bd8SMatthew G Knepley   PetscFunctionBegin;
577031823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57714f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5772efd4aadfSBarry Smith   if (!snes->npc) {
5773ec785e5bSStefano Zampini     void *ctx;
5774ec785e5bSStefano Zampini 
57759566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
57769566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
57779566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57789566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
57799566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5780fb87a551SStefano Zampini     if (snes->ops->usercompute) {
578149abdd8aSBarry Smith       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy));
5782fb87a551SStefano Zampini     } else {
5783ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5784ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5785fb87a551SStefano Zampini     }
57869566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
578731823bd8SMatthew G Knepley   }
5788efd4aadfSBarry Smith   *pc = snes->npc;
57893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
579031823bd8SMatthew G Knepley }
579131823bd8SMatthew G Knepley 
57923ad1a0b9SPatrick Farrell /*@
57930b4b7b1cSBarry Smith   SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES`
57943ad1a0b9SPatrick Farrell 
57953ad1a0b9SPatrick Farrell   Not Collective
57963ad1a0b9SPatrick Farrell 
57973ad1a0b9SPatrick Farrell   Input Parameter:
5798f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57993ad1a0b9SPatrick Farrell 
58003ad1a0b9SPatrick Farrell   Output Parameter:
5801420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
58023ad1a0b9SPatrick Farrell 
58033ad1a0b9SPatrick Farrell   Level: developer
58043ad1a0b9SPatrick Farrell 
58051cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
58063ad1a0b9SPatrick Farrell @*/
5807d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5808d71ae5a4SJacob Faibussowitsch {
58093ad1a0b9SPatrick Farrell   PetscFunctionBegin;
58103ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5811835f2295SStefano Zampini   PetscAssertPointer(has_npc, 2);
5812835f2295SStefano Zampini   *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE;
58133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58143ad1a0b9SPatrick Farrell }
58153ad1a0b9SPatrick Farrell 
5816c40d0f55SPeter Brune /*@
581762842358SBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`.
5818c40d0f55SPeter Brune 
5819c3339decSBarry Smith   Logically Collective
5820c40d0f55SPeter Brune 
5821c40d0f55SPeter Brune   Input Parameter:
5822f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5823c40d0f55SPeter Brune 
5824c40d0f55SPeter Brune   Output Parameter:
5825c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5826c40d0f55SPeter Brune .vb
58272d547940SBarry Smith       PC_LEFT  - left preconditioning
58282d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5829c40d0f55SPeter Brune .ve
5830c40d0f55SPeter Brune 
5831f6dfbefdSBarry Smith   Options Database Key:
583267b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5833c40d0f55SPeter Brune 
5834dc4c0fb0SBarry Smith   Level: intermediate
5835dc4c0fb0SBarry Smith 
5836f6dfbefdSBarry Smith   Note:
5837f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
58382d547940SBarry Smith 
583962842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5840c40d0f55SPeter Brune @*/
5841d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5842d71ae5a4SJacob Faibussowitsch {
5843c40d0f55SPeter Brune   PetscFunctionBegin;
5844c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5845c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5846b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
584754c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5848efd4aadfSBarry Smith   snes->npcside = side;
58493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5850c40d0f55SPeter Brune }
5851c40d0f55SPeter Brune 
5852c40d0f55SPeter Brune /*@
585362842358SBarry Smith   SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`.
5854c40d0f55SPeter Brune 
5855c40d0f55SPeter Brune   Not Collective
5856c40d0f55SPeter Brune 
5857c40d0f55SPeter Brune   Input Parameter:
5858f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5859c40d0f55SPeter Brune 
5860c40d0f55SPeter Brune   Output Parameter:
5861c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5862c40d0f55SPeter Brune .vb
5863f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5864f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5865c40d0f55SPeter Brune .ve
5866c40d0f55SPeter Brune 
5867c40d0f55SPeter Brune   Level: intermediate
5868c40d0f55SPeter Brune 
586962842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5870c40d0f55SPeter Brune @*/
5871d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5872d71ae5a4SJacob Faibussowitsch {
5873c40d0f55SPeter Brune   PetscFunctionBegin;
5874c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58754f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5876efd4aadfSBarry Smith   *side = snes->npcside;
58773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5878c40d0f55SPeter Brune }
5879c40d0f55SPeter Brune 
58809e764e56SPeter Brune /*@
58810b4b7b1cSBarry Smith   SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES`
58829e764e56SPeter Brune 
5883c3339decSBarry Smith   Collective
58849e764e56SPeter Brune 
58859e764e56SPeter Brune   Input Parameters:
5886f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
58879e764e56SPeter Brune - linesearch - the linesearch object
58889e764e56SPeter Brune 
5889dc4c0fb0SBarry Smith   Level: developer
5890dc4c0fb0SBarry Smith 
5891f6dfbefdSBarry Smith   Note:
5892420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
58939e764e56SPeter Brune   to configure it using the API).
58949e764e56SPeter Brune 
5895420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
58969e764e56SPeter Brune @*/
5897d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5898d71ae5a4SJacob Faibussowitsch {
58999e764e56SPeter Brune   PetscFunctionBegin;
59009e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5901f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
59029e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
59039566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
59049566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5905f5af7f23SKarl Rupp 
59069e764e56SPeter Brune   snes->linesearch = linesearch;
59073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59089e764e56SPeter Brune }
59099e764e56SPeter Brune 
5910a34ceb2aSJed Brown /*@
591162842358SBarry Smith   SNESGetLineSearch - Returns the line search associated with the `SNES`.
59129e764e56SPeter Brune 
59139e764e56SPeter Brune   Not Collective
59149e764e56SPeter Brune 
59159e764e56SPeter Brune   Input Parameter:
5916f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
59179e764e56SPeter Brune 
59189e764e56SPeter Brune   Output Parameter:
59199e764e56SPeter Brune . linesearch - linesearch context
59209e764e56SPeter Brune 
5921162e0bf5SPeter Brune   Level: beginner
59229e764e56SPeter Brune 
592362842358SBarry Smith   Notes:
592462842358SBarry Smith   It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`.
592562842358SBarry Smith 
592662842358SBarry Smith   You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options.
592762842358SBarry Smith 
592862842358SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`
59299e764e56SPeter Brune @*/
5930d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5931d71ae5a4SJacob Faibussowitsch {
59329e764e56SPeter Brune   const char *optionsprefix;
59339e764e56SPeter Brune 
59349e764e56SPeter Brune   PetscFunctionBegin;
59359e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59364f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
59379e764e56SPeter Brune   if (!snes->linesearch) {
59389566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
59399566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
59409566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
59419566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
59429566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
59439e764e56SPeter Brune   }
59449e764e56SPeter Brune   *linesearch = snes->linesearch;
59453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59469e764e56SPeter Brune }
5947