xref: /petsc/src/snes/interface/snes.c (revision 1dfd762287099e882ed7390af965e6df7dac208c)
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 
1125*1dfd7622SMatthew Knepley   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference functions", "None", &snes->testFunc));
1126*1dfd7622SMatthew Knepley   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &snes->testJac));
1127*1dfd7622SMatthew Knepley 
1128c40d0f55SPeter Brune   flg = PETSC_FALSE;
11299566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11319566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1132c40d0f55SPeter Brune 
1133e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11348a70d858SHong Zhang   /*
11358a70d858SHong Zhang     Publish convergence information using SAWs
11368a70d858SHong Zhang   */
11378a70d858SHong Zhang   flg = PETSC_FALSE;
11389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11398a70d858SHong Zhang   if (flg) {
11408a70d858SHong Zhang     void *ctx;
11419566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11429566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11438a70d858SHong Zhang   }
11448a70d858SHong Zhang #endif
11458a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1146b90c6cbeSBarry Smith   {
1147b90c6cbeSBarry Smith     PetscBool set;
1148b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11499566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11501baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1151b90c6cbeSBarry Smith   }
1152b90c6cbeSBarry Smith #endif
1153b90c6cbeSBarry Smith 
115448a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
115576b2cf59SMatthew Knepley 
1156dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11575d973c19SBarry Smith 
11585d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1159dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1160d0609cedSBarry Smith   PetscOptionsEnd();
11614bbc92c1SBarry Smith 
1162d8d34be6SBarry Smith   if (snes->linesearch) {
11639566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11649566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1165d8d34be6SBarry Smith   }
11669e764e56SPeter Brune 
11676aa5e7e9SBarry Smith   if (snes->usesksp) {
11689566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11699566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11709566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11716aa5e7e9SBarry Smith   }
11726991f827SBarry Smith 
1173b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11749566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
117648a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11771baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1178b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1180b3cd9a81SMatthew G. Knepley }
1181b3cd9a81SMatthew G. Knepley 
1182b3cd9a81SMatthew G. Knepley /*@
1183420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1184b3cd9a81SMatthew G. Knepley 
1185c3339decSBarry Smith   Collective
1186b3cd9a81SMatthew G. Knepley 
1187b3cd9a81SMatthew G. Knepley   Input Parameter:
1188f6dfbefdSBarry Smith . snes - the `SNES` context
1189b3cd9a81SMatthew G. Knepley 
1190420bcc1bSBarry Smith   Level: advanced
1191b3cd9a81SMatthew G. Knepley 
11921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1193b3cd9a81SMatthew G. Knepley @*/
1194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1195d71ae5a4SJacob Faibussowitsch {
1196b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11979566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11999b94acceSBarry Smith }
12009b94acceSBarry Smith 
1201bb9467b5SJed Brown /*@C
1202d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1203d25893d9SBarry Smith   the nonlinear solvers.
1204d25893d9SBarry Smith 
1205dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1206d25893d9SBarry Smith 
1207d25893d9SBarry Smith   Input Parameters:
1208f6dfbefdSBarry Smith + snes    - the `SNES` context
1209d25893d9SBarry Smith . compute - function to compute the context
121049abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence
1211d25893d9SBarry Smith 
1212420bcc1bSBarry Smith   Calling sequence of `compute`:
1213420bcc1bSBarry Smith + snes - the `SNES` context
1214420bcc1bSBarry Smith - ctx  - context to be computed
1215420bcc1bSBarry Smith 
1216d25893d9SBarry Smith   Level: intermediate
1217d25893d9SBarry Smith 
1218f6dfbefdSBarry Smith   Note:
1219f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1220f6dfbefdSBarry Smith 
1221f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1222f6dfbefdSBarry Smith 
122349abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn`
1224d25893d9SBarry Smith @*/
122549abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy)
1226d71ae5a4SJacob Faibussowitsch {
1227d25893d9SBarry Smith   PetscFunctionBegin;
1228d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1229d25893d9SBarry Smith   snes->ops->usercompute = compute;
123049abdd8aSBarry Smith   snes->ops->ctxdestroy  = destroy;
12313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1232d25893d9SBarry Smith }
1233a847f771SSatish Balay 
1234b07ff414SBarry Smith /*@
1235f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12369b94acceSBarry Smith 
1237c3339decSBarry Smith   Logically Collective
1238fee21e36SBarry Smith 
1239c7afd0dbSLois Curfman McInnes   Input Parameters:
1240f6dfbefdSBarry Smith + snes - the `SNES` context
1241ce78bad3SBarry Smith - ctx  - the user context
1242c7afd0dbSLois Curfman McInnes 
124336851e7fSLois Curfman McInnes   Level: intermediate
124436851e7fSLois Curfman McInnes 
1245f6dfbefdSBarry Smith   Notes:
1246ce78bad3SBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian computation, or other evaluation function
1247f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1248f6dfbefdSBarry Smith 
1249f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1250f6dfbefdSBarry Smith 
1251420bcc1bSBarry Smith   Fortran Note:
1252ce78bad3SBarry 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
1253ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `SNESGetApplicationContext()` for
1254ce78bad3SBarry Smith   an example.
1255daf670e6SBarry Smith 
12561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12579b94acceSBarry Smith @*/
125849abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx)
1259d71ae5a4SJacob Faibussowitsch {
1260b07ff414SBarry Smith   KSP ksp;
12611b2093e4SBarry Smith 
12623a40ed3dSBarry Smith   PetscFunctionBegin;
12630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12649566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
126549abdd8aSBarry Smith   PetscCall(KSPSetApplicationContext(ksp, ctx));
126649abdd8aSBarry Smith   snes->ctx = ctx;
12673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12689b94acceSBarry Smith }
126974679c65SBarry Smith 
1270b07ff414SBarry Smith /*@
12719b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1272420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12739b94acceSBarry Smith 
1274c7afd0dbSLois Curfman McInnes   Not Collective
1275c7afd0dbSLois Curfman McInnes 
12769b94acceSBarry Smith   Input Parameter:
1277f6dfbefdSBarry Smith . snes - `SNES` context
12789b94acceSBarry Smith 
12799b94acceSBarry Smith   Output Parameter:
128049abdd8aSBarry Smith . ctx - user context
12819b94acceSBarry Smith 
128236851e7fSLois Curfman McInnes   Level: intermediate
128336851e7fSLois Curfman McInnes 
1284ce78bad3SBarry Smith   Fortran Notes:
1285ce78bad3SBarry 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
1286ce78bad3SBarry Smith   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
1287ce78bad3SBarry Smith .vb
1288ce78bad3SBarry Smith   Interface SNESGetApplicationContext
1289ce78bad3SBarry Smith     Subroutine SNESGetApplicationContext(snes,ctx,ierr)
1290ce78bad3SBarry Smith   #include <petsc/finclude/petscsnes.h>
1291ce78bad3SBarry Smith       use petscsnes
1292ce78bad3SBarry Smith       SNES snes
1293ce78bad3SBarry Smith       type(tUsertype), pointer :: ctx
1294ce78bad3SBarry Smith       PetscErrorCode ierr
1295ce78bad3SBarry Smith     End Subroutine
1296ce78bad3SBarry Smith   End Interface SNESGetApplicationContext
1297ce78bad3SBarry Smith .ve
1298ce78bad3SBarry Smith 
1299bfe80ac4SPierre Jolivet   The prototype for `ctx` must be
1300ce78bad3SBarry Smith .vb
1301ce78bad3SBarry Smith   type(tUsertype), pointer :: ctx
1302ce78bad3SBarry Smith .ve
1303dc4c0fb0SBarry Smith 
1304420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13059b94acceSBarry Smith @*/
1306ce78bad3SBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, PeCtx ctx)
1307d71ae5a4SJacob Faibussowitsch {
13083a40ed3dSBarry Smith   PetscFunctionBegin;
13090700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
131049abdd8aSBarry Smith   *(void **)ctx = snes->ctx;
13113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13129b94acceSBarry Smith }
131374679c65SBarry Smith 
13149b94acceSBarry Smith /*@
1315420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13163565c898SBarry Smith 
1317dc4c0fb0SBarry Smith   Logically Collective
13183565c898SBarry Smith 
13193565c898SBarry Smith   Input Parameters:
1320f6dfbefdSBarry Smith + snes        - `SNES` context
1321f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1322f6dfbefdSBarry 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
1323420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13243565c898SBarry Smith 
1325f6dfbefdSBarry Smith   Options Database Keys:
132601c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1327f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1328ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1329ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13303565c898SBarry Smith 
13313565c898SBarry Smith   Level: intermediate
13323565c898SBarry Smith 
1333f6dfbefdSBarry Smith   Note:
1334420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1335420bcc1bSBarry Smith   and computing explicitly with
1336f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1337ec5066bdSBarry Smith 
1338420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13393565c898SBarry Smith @*/
1340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1341d71ae5a4SJacob Faibussowitsch {
13423565c898SBarry Smith   PetscFunctionBegin;
13433565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
134488b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
134588b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13464ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13473565c898SBarry Smith   snes->mf_operator = mf_operator;
13483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13493565c898SBarry Smith }
13503565c898SBarry Smith 
13513565c898SBarry Smith /*@
1352dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13533565c898SBarry Smith 
1354420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13553565c898SBarry Smith 
13563565c898SBarry Smith   Input Parameter:
1357f6dfbefdSBarry Smith . snes - `SNES` context
13583565c898SBarry Smith 
13593565c898SBarry Smith   Output Parameters:
1360f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1361f6dfbefdSBarry 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
13623565c898SBarry Smith 
13633565c898SBarry Smith   Level: intermediate
13643565c898SBarry Smith 
13651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13663565c898SBarry Smith @*/
1367d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1368d71ae5a4SJacob Faibussowitsch {
13693565c898SBarry Smith   PetscFunctionBegin;
13703565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13713565c898SBarry Smith   if (mf) *mf = snes->mf;
13723565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13743565c898SBarry Smith }
13753565c898SBarry Smith 
13763565c898SBarry Smith /*@
1377420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13789b94acceSBarry Smith 
1379c7afd0dbSLois Curfman McInnes   Not Collective
1380c7afd0dbSLois Curfman McInnes 
13819b94acceSBarry Smith   Input Parameter:
1382f6dfbefdSBarry Smith . snes - `SNES` context
13839b94acceSBarry Smith 
13849b94acceSBarry Smith   Output Parameter:
13859b94acceSBarry Smith . iter - iteration number
13869b94acceSBarry Smith 
1387dc4c0fb0SBarry Smith   Level: intermediate
1388dc4c0fb0SBarry Smith 
1389c8228a4eSBarry Smith   Notes:
1390c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1391c8228a4eSBarry Smith 
1392c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1393f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
139408405cd6SLois Curfman McInnes .vb
139508405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
139608405cd6SLois Curfman McInnes       if (!(it % 2)) {
139708405cd6SLois Curfman McInnes         [compute Jacobian here]
139808405cd6SLois Curfman McInnes       }
139908405cd6SLois Curfman McInnes .ve
1400f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1401f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1402c8228a4eSBarry Smith 
1403f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1404c04deec6SBarry Smith 
1405420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14069b94acceSBarry Smith @*/
1407d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1408d71ae5a4SJacob Faibussowitsch {
14093a40ed3dSBarry Smith   PetscFunctionBegin;
14100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14114f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14129b94acceSBarry Smith   *iter = snes->iter;
14133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14149b94acceSBarry Smith }
141574679c65SBarry Smith 
1416360c497dSPeter Brune /*@
1417360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1418360c497dSPeter Brune 
1419360c497dSPeter Brune   Not Collective
1420360c497dSPeter Brune 
1421d8d19677SJose E. Roman   Input Parameters:
1422f6dfbefdSBarry Smith + snes - `SNES` context
1423a2b725a8SWilliam Gropp - iter - iteration number
1424360c497dSPeter Brune 
1425360c497dSPeter Brune   Level: developer
1426360c497dSPeter Brune 
1427420bcc1bSBarry Smith   Note:
1428420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1429420bcc1bSBarry Smith 
14301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1431360c497dSPeter Brune @*/
1432d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1433d71ae5a4SJacob Faibussowitsch {
1434360c497dSPeter Brune   PetscFunctionBegin;
1435360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14369566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1437360c497dSPeter Brune   snes->iter = iter;
14389566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1440360c497dSPeter Brune }
1441360c497dSPeter Brune 
14429b94acceSBarry Smith /*@
1443b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1444420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14459b94acceSBarry Smith 
1446c7afd0dbSLois Curfman McInnes   Not Collective
1447c7afd0dbSLois Curfman McInnes 
14489b94acceSBarry Smith   Input Parameter:
1449f6dfbefdSBarry Smith . snes - `SNES` context
14509b94acceSBarry Smith 
14519b94acceSBarry Smith   Output Parameter:
14529b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14539b94acceSBarry Smith 
1454dc4c0fb0SBarry Smith   Level: intermediate
1455dc4c0fb0SBarry Smith 
1456f6dfbefdSBarry Smith   Note:
1457f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1458c96a6f78SLois Curfman McInnes 
14591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1460db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14619b94acceSBarry Smith @*/
1462d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1463d71ae5a4SJacob Faibussowitsch {
14643a40ed3dSBarry Smith   PetscFunctionBegin;
14650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14664f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
146750ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
146950ffb88aSMatthew Knepley }
147050ffb88aSMatthew Knepley 
147150ffb88aSMatthew Knepley /*@
1472b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1473420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
147450ffb88aSMatthew Knepley 
147550ffb88aSMatthew Knepley   Not Collective
147650ffb88aSMatthew Knepley 
147750ffb88aSMatthew Knepley   Input Parameters:
1478f6dfbefdSBarry Smith + snes     - `SNES` context
147977e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
148050ffb88aSMatthew Knepley 
1481420bcc1bSBarry Smith   Options Database Key:
1482420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1483420bcc1bSBarry Smith 
148450ffb88aSMatthew Knepley   Level: intermediate
148550ffb88aSMatthew Knepley 
1486420bcc1bSBarry Smith   Developer Note:
1487420bcc1bSBarry Smith   The options database key is wrong for this function name
1488420bcc1bSBarry Smith 
14891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1490db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
149150ffb88aSMatthew Knepley @*/
1492d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1493d71ae5a4SJacob Faibussowitsch {
149450ffb88aSMatthew Knepley   PetscFunctionBegin;
14950700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
149677e5a1f9SBarry Smith 
149777e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
14981690c2aeSBarry Smith     snes->maxFailures = PETSC_INT_MAX;
149977e5a1f9SBarry Smith   } else {
150077e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
150150ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
150277e5a1f9SBarry Smith   }
15033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
150450ffb88aSMatthew Knepley }
150550ffb88aSMatthew Knepley 
150650ffb88aSMatthew Knepley /*@
1507b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1508420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
150950ffb88aSMatthew Knepley 
151050ffb88aSMatthew Knepley   Not Collective
151150ffb88aSMatthew Knepley 
151250ffb88aSMatthew Knepley   Input Parameter:
151320f4b53cSBarry Smith . snes - `SNES` context
151450ffb88aSMatthew Knepley 
151550ffb88aSMatthew Knepley   Output Parameter:
151650ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
151750ffb88aSMatthew Knepley 
151850ffb88aSMatthew Knepley   Level: intermediate
151950ffb88aSMatthew Knepley 
15201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1521db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
152250ffb88aSMatthew Knepley @*/
1523d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1524d71ae5a4SJacob Faibussowitsch {
152550ffb88aSMatthew Knepley   PetscFunctionBegin;
15260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15274f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
152850ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15309b94acceSBarry Smith }
1531a847f771SSatish Balay 
15322541af92SBarry Smith /*@
15332541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1534420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15352541af92SBarry Smith 
15362541af92SBarry Smith   Not Collective
15372541af92SBarry Smith 
15382541af92SBarry Smith   Input Parameter:
1539f6dfbefdSBarry Smith . snes - `SNES` context
15402541af92SBarry Smith 
15412541af92SBarry Smith   Output Parameter:
15422541af92SBarry Smith . nfuncs - number of evaluations
15432541af92SBarry Smith 
15442541af92SBarry Smith   Level: intermediate
15452541af92SBarry Smith 
1546f6dfbefdSBarry Smith   Note:
1547f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1548971e163fSPeter Brune 
15491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15502541af92SBarry Smith @*/
1551d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1552d71ae5a4SJacob Faibussowitsch {
15532541af92SBarry Smith   PetscFunctionBegin;
15540700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15554f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15562541af92SBarry Smith   *nfuncs = snes->nfuncs;
15573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15582541af92SBarry Smith }
15592541af92SBarry Smith 
15603d4c4710SBarry Smith /*@
15613d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1562420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15633d4c4710SBarry Smith 
15643d4c4710SBarry Smith   Not Collective
15653d4c4710SBarry Smith 
15663d4c4710SBarry Smith   Input Parameter:
1567f6dfbefdSBarry Smith . snes - `SNES` context
15683d4c4710SBarry Smith 
15693d4c4710SBarry Smith   Output Parameter:
15703d4c4710SBarry Smith . nfails - number of failed solves
15713d4c4710SBarry Smith 
1572f6dfbefdSBarry Smith   Options Database Key:
15739d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15749d85da0cSMatthew G. Knepley 
1575f6dfbefdSBarry Smith   Level: intermediate
1576f6dfbefdSBarry Smith 
1577f6dfbefdSBarry Smith   Note:
1578f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15793d4c4710SBarry Smith 
15801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15813d4c4710SBarry Smith @*/
1582d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1583d71ae5a4SJacob Faibussowitsch {
15843d4c4710SBarry Smith   PetscFunctionBegin;
15850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15864f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15873d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15893d4c4710SBarry Smith }
15903d4c4710SBarry Smith 
15913d4c4710SBarry Smith /*@
15923d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1593f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15943d4c4710SBarry Smith 
1595c3339decSBarry Smith   Logically Collective
15963d4c4710SBarry Smith 
15973d4c4710SBarry Smith   Input Parameters:
1598f6dfbefdSBarry Smith + snes     - `SNES` context
159977e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16003d4c4710SBarry Smith 
1601f6dfbefdSBarry Smith   Options Database Key:
16029d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16039d85da0cSMatthew G. Knepley 
1604dc4c0fb0SBarry Smith   Level: intermediate
1605dc4c0fb0SBarry Smith 
1606f6dfbefdSBarry Smith   Note:
1607f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16083d4c4710SBarry Smith 
1609420bcc1bSBarry Smith   Developer Note:
1610420bcc1bSBarry Smith   The options database key is wrong for this function name
1611420bcc1bSBarry Smith 
16121cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16133d4c4710SBarry Smith @*/
1614d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1615d71ae5a4SJacob Faibussowitsch {
16163d4c4710SBarry Smith   PetscFunctionBegin;
16170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1618c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
161977e5a1f9SBarry Smith 
162077e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
16211690c2aeSBarry Smith     snes->maxLinearSolveFailures = PETSC_INT_MAX;
162277e5a1f9SBarry Smith   } else {
162377e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16243d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
162577e5a1f9SBarry Smith   }
16263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16273d4c4710SBarry Smith }
16283d4c4710SBarry Smith 
16293d4c4710SBarry Smith /*@
16303d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1631f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16323d4c4710SBarry Smith 
16333d4c4710SBarry Smith   Not Collective
16343d4c4710SBarry Smith 
16353d4c4710SBarry Smith   Input Parameter:
1636f6dfbefdSBarry Smith . snes - `SNES` context
16373d4c4710SBarry Smith 
16383d4c4710SBarry Smith   Output Parameter:
16393d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16403d4c4710SBarry Smith 
16413d4c4710SBarry Smith   Level: intermediate
16423d4c4710SBarry Smith 
1643f6dfbefdSBarry Smith   Note:
1644f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16453d4c4710SBarry Smith 
16461cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16473d4c4710SBarry Smith @*/
1648d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1649d71ae5a4SJacob Faibussowitsch {
16503d4c4710SBarry Smith   PetscFunctionBegin;
16510700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16524f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16533d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16553d4c4710SBarry Smith }
16563d4c4710SBarry Smith 
1657c96a6f78SLois Curfman McInnes /*@
1658b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1659420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1660c96a6f78SLois Curfman McInnes 
1661c7afd0dbSLois Curfman McInnes   Not Collective
1662c7afd0dbSLois Curfman McInnes 
1663c96a6f78SLois Curfman McInnes   Input Parameter:
1664f6dfbefdSBarry Smith . snes - `SNES` context
1665c96a6f78SLois Curfman McInnes 
1666c96a6f78SLois Curfman McInnes   Output Parameter:
1667c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1668c96a6f78SLois Curfman McInnes 
1669dc4c0fb0SBarry Smith   Level: intermediate
1670dc4c0fb0SBarry Smith 
1671c96a6f78SLois Curfman McInnes   Notes:
1672f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1673c96a6f78SLois Curfman McInnes 
1674f6dfbefdSBarry 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
1675f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1676010be392SBarry Smith 
16771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1678c96a6f78SLois Curfman McInnes @*/
1679d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1680d71ae5a4SJacob Faibussowitsch {
16813a40ed3dSBarry Smith   PetscFunctionBegin;
16820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16834f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1684c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1686c96a6f78SLois Curfman McInnes }
1687c96a6f78SLois Curfman McInnes 
1688971e163fSPeter Brune /*@
1689971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1690f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1691971e163fSPeter Brune 
1692c3339decSBarry Smith   Logically Collective
1693971e163fSPeter Brune 
1694d8d19677SJose E. Roman   Input Parameters:
1695f6dfbefdSBarry Smith + snes  - `SNES` context
1696f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1697971e163fSPeter Brune 
1698971e163fSPeter Brune   Level: developer
1699971e163fSPeter Brune 
17001cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1701971e163fSPeter Brune @*/
1702d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1703d71ae5a4SJacob Faibussowitsch {
1704971e163fSPeter Brune   PetscFunctionBegin;
1705971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1706971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1707971e163fSPeter Brune   snes->counters_reset = reset;
17083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1709971e163fSPeter Brune }
1710971e163fSPeter Brune 
17112999313aSBarry Smith /*@
171212b1dd1aSStefano Zampini   SNESResetCounters - Reset counters for linear iterations and function evaluations.
171312b1dd1aSStefano Zampini 
171412b1dd1aSStefano Zampini   Logically Collective
171512b1dd1aSStefano Zampini 
171612b1dd1aSStefano Zampini   Input Parameters:
171712b1dd1aSStefano Zampini . snes - `SNES` context
171812b1dd1aSStefano Zampini 
171912b1dd1aSStefano Zampini   Level: developer
172012b1dd1aSStefano Zampini 
172112b1dd1aSStefano Zampini   Note:
172212b1dd1aSStefano Zampini   It honors the flag set with `SNESSetCountersReset()`
172312b1dd1aSStefano Zampini 
172412b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
172512b1dd1aSStefano Zampini @*/
172612b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
172712b1dd1aSStefano Zampini {
172812b1dd1aSStefano Zampini   PetscFunctionBegin;
172912b1dd1aSStefano Zampini   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
173012b1dd1aSStefano Zampini   if (snes->counters_reset) {
173112b1dd1aSStefano Zampini     snes->nfuncs      = 0;
173212b1dd1aSStefano Zampini     snes->linear_its  = 0;
173312b1dd1aSStefano Zampini     snes->numFailures = 0;
173412b1dd1aSStefano Zampini   }
173512b1dd1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
173612b1dd1aSStefano Zampini }
173712b1dd1aSStefano Zampini 
173812b1dd1aSStefano Zampini /*@
1739f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17402999313aSBarry Smith 
1741420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17422999313aSBarry Smith 
17432999313aSBarry Smith   Input Parameters:
1744f6dfbefdSBarry Smith + snes - the `SNES` context
1745f6dfbefdSBarry Smith - ksp  - the `KSP` context
17462999313aSBarry Smith 
1747dc4c0fb0SBarry Smith   Level: developer
1748dc4c0fb0SBarry Smith 
17492999313aSBarry Smith   Notes:
1750f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17512999313aSBarry Smith   so this routine is rarely needed.
17522999313aSBarry Smith 
1753f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1754420bcc1bSBarry Smith   decreased by one when this is called.
17552999313aSBarry Smith 
175642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17572999313aSBarry Smith @*/
1758d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1759d71ae5a4SJacob Faibussowitsch {
17602999313aSBarry Smith   PetscFunctionBegin;
17610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17620700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17632999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17649566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17659566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17662999313aSBarry Smith   snes->ksp = ksp;
17673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17682999313aSBarry Smith }
17692999313aSBarry Smith 
177052baeb72SSatish Balay /*@
177177e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
177277e5a1f9SBarry Smith   currently contain default values
177377e5a1f9SBarry Smith 
177477e5a1f9SBarry Smith   Collective
177577e5a1f9SBarry Smith 
177677e5a1f9SBarry Smith   Input Parameter:
177777e5a1f9SBarry Smith . snes - the `SNES` object
177877e5a1f9SBarry Smith 
177977e5a1f9SBarry Smith   Level: developer
178077e5a1f9SBarry Smith 
178177e5a1f9SBarry Smith   Developer Note:
178277e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
178377e5a1f9SBarry Smith 
178477e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
178577e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
178677e5a1f9SBarry Smith @*/
178777e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
178877e5a1f9SBarry Smith {
178977e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
179077e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
179177e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
179277e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
179377e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
179477e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
179577e5a1f9SBarry Smith   return PETSC_SUCCESS;
179677e5a1f9SBarry Smith }
179777e5a1f9SBarry Smith 
179877e5a1f9SBarry Smith /*@
1799dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
18009b94acceSBarry Smith 
1801d083f849SBarry Smith   Collective
1802c7afd0dbSLois Curfman McInnes 
1803f6dfbefdSBarry Smith   Input Parameter:
1804906ed7ccSBarry Smith . comm - MPI communicator
18059b94acceSBarry Smith 
18069b94acceSBarry Smith   Output Parameter:
180720f4b53cSBarry Smith . outsnes - the new `SNES` context
18089b94acceSBarry Smith 
1809c7afd0dbSLois Curfman McInnes   Options Database Keys:
18107addb90fSBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no matrix to construct a preconditioner
18117addb90fSBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided matrix as set by `SNESSetJacobian()`
1812dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1813c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1814c1f60f51SBarry Smith 
181536851e7fSLois Curfman McInnes   Level: beginner
181636851e7fSLois Curfman McInnes 
181795452b02SPatrick Sanan   Developer Notes:
1818f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1819efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1820f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1821f6dfbefdSBarry Smith   in `SNESView()`.
1822efd4aadfSBarry Smith 
1823f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1824f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1825f6dfbefdSBarry Smith 
18267addb90fSBarry Smith   `SNES` always creates the `snes->kspconvctx` even though it is used by only one type. This should be fixed.
1827efd4aadfSBarry Smith 
1828e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18299b94acceSBarry Smith @*/
1830d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1831d71ae5a4SJacob Faibussowitsch {
18329b94acceSBarry Smith   SNES       snes;
1833fa9f3622SBarry Smith   SNESKSPEW *kctx;
183437fcc0dbSBarry Smith 
18353a40ed3dSBarry Smith   PetscFunctionBegin;
18364f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18379566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18388ba1e511SMatthew Knepley 
18399566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18408d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18412c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18429b94acceSBarry Smith   snes->norm           = 0.0;
1843c1e67a49SFande Kong   snes->xnorm          = 0.0;
1844c1e67a49SFande Kong   snes->ynorm          = 0.0;
1845365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18466c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1847b4874afaSBarry Smith   snes->ttol           = 0.0;
184877e5a1f9SBarry Smith 
1849e37c518bSBarry Smith   snes->rnorm0               = 0;
18509b94acceSBarry Smith   snes->nfuncs               = 0;
185150ffb88aSMatthew Knepley   snes->numFailures          = 0;
185250ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18537a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1854e35cf81dSBarry Smith   snes->lagjacobian          = 1;
185537ec4e1aSPeter Brune   snes->jac_iter             = 0;
185637ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1857a8054027SBarry Smith   snes->lagpreconditioner    = 1;
185837ec4e1aSPeter Brune   snes->pre_iter             = 0;
185937ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1860639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1861c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18629e5d0892SLisandro Dalcin   snes->data                 = NULL;
18634dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1864186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18656f24a144SLois Curfman McInnes   snes->nwork                = 0;
18669e5d0892SLisandro Dalcin   snes->work                 = NULL;
186758c9b817SLisandro Dalcin   snes->nvwork               = 0;
18689e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1869758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1870758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18710298fd71SBarry Smith   snes->conv_hist            = NULL;
18720298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1873758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1874971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1875e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1876184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1877efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1878b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1879c40d0f55SPeter Brune 
1880d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1881d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1882d8f46077SPeter Brune   snes->mf_version  = 1;
1883d8f46077SPeter Brune 
18843d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18853d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18863d4c4710SBarry Smith 
1887349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
188876bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1889349187a7SBarry Smith 
18904fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18914fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
18924fc747eaSLawrence Mitchell 
18939b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18944dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1895f5af7f23SKarl Rupp 
1896835f2295SStefano Zampini   snes->kspconvctx  = kctx;
18979b94acceSBarry Smith   kctx->version     = 2;
18980f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
18999b94acceSBarry Smith                              this was too large for some test cases */
190075567043SBarry Smith   kctx->rtol_last   = 0.0;
19010f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
19029b94acceSBarry Smith   kctx->gamma       = 1.0;
19030f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
190471f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
19050f0abf79SStefano Zampini   kctx->threshold   = 0.1;
190675567043SBarry Smith   kctx->lresid_last = 0.0;
190775567043SBarry Smith   kctx->norm_last   = 0.0;
19089b94acceSBarry Smith 
19090f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
19100f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
19110f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
19120f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
19130f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19140f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19150f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19160f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19170f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19180f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19190f0abf79SStefano Zampini 
1920b50c806fSBarry Smith   PetscCall(SNESParametersInitialize(snes));
19219b94acceSBarry Smith   *outsnes = snes;
19223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19239b94acceSBarry Smith }
19249b94acceSBarry Smith 
19259b94acceSBarry Smith /*@C
19269b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1927f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19289b94acceSBarry Smith   equations.
19299b94acceSBarry Smith 
1930c3339decSBarry Smith   Logically Collective
1931fee21e36SBarry Smith 
1932c7afd0dbSLois Curfman McInnes   Input Parameters:
1933f6dfbefdSBarry Smith + snes - the `SNES` context
1934dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19358434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1936c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1937dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19389b94acceSBarry Smith 
193936851e7fSLois Curfman McInnes   Level: beginner
194036851e7fSLois Curfman McInnes 
19418434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19429b94acceSBarry Smith @*/
19438434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1944d71ae5a4SJacob Faibussowitsch {
19456cab3a1bSJed Brown   DM dm;
19466cab3a1bSJed Brown 
19473a40ed3dSBarry Smith   PetscFunctionBegin;
19480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1949d2a683ecSLisandro Dalcin   if (r) {
1950d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1951d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19529566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19539566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
195485385478SLisandro Dalcin     snes->vec_func = r;
1955d2a683ecSLisandro Dalcin   }
19569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19579566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
195848a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19609b94acceSBarry Smith }
19619b94acceSBarry Smith 
1962e4ed7901SPeter Brune /*@C
19630b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1964e4ed7901SPeter Brune 
1965c3339decSBarry Smith   Logically Collective
1966e4ed7901SPeter Brune 
1967e4ed7901SPeter Brune   Input Parameters:
1968f6dfbefdSBarry Smith + snes - the `SNES` context
1969e4ed7901SPeter Brune - f    - vector to store function value
1970e4ed7901SPeter Brune 
1971dc4c0fb0SBarry Smith   Level: developer
1972dc4c0fb0SBarry Smith 
1973e4ed7901SPeter Brune   Notes:
1974e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1975e4ed7901SPeter Brune 
1976f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1977e4ed7901SPeter Brune 
19781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1979e4ed7901SPeter Brune @*/
1980d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1981d71ae5a4SJacob Faibussowitsch {
1982e4ed7901SPeter Brune   Vec vec_func;
1983e4ed7901SPeter Brune 
1984e4ed7901SPeter Brune   PetscFunctionBegin;
1985e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1986e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1987e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1988efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1989902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19903ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1991902f982fSPeter Brune   }
19929566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19939566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1994f5af7f23SKarl Rupp 
1995217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1997e4ed7901SPeter Brune }
1998e4ed7901SPeter Brune 
1999534ebe21SPeter Brune /*@
2000f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
2001f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
2002534ebe21SPeter Brune 
2003c3339decSBarry Smith   Logically Collective
2004534ebe21SPeter Brune 
2005534ebe21SPeter Brune   Input Parameters:
2006f6dfbefdSBarry Smith + snes         - the `SNES` context
2007365a6726SPeter Brune - normschedule - the frequency of norm computation
2008534ebe21SPeter Brune 
2009517f1916SMatthew G. Knepley   Options Database Key:
201067b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2011517f1916SMatthew G. Knepley 
2012dc4c0fb0SBarry Smith   Level: advanced
2013dc4c0fb0SBarry Smith 
2014534ebe21SPeter Brune   Notes:
2015f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2016534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2017534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2018f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2019534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2020534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2021534ebe21SPeter Brune   their solution.
2022534ebe21SPeter Brune 
2023e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2024534ebe21SPeter Brune @*/
2025d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2026d71ae5a4SJacob Faibussowitsch {
2027534ebe21SPeter Brune   PetscFunctionBegin;
2028534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2029365a6726SPeter Brune   snes->normschedule = normschedule;
20303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2031534ebe21SPeter Brune }
2032534ebe21SPeter Brune 
2033534ebe21SPeter Brune /*@
2034f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2035f6dfbefdSBarry Smith   of the `SNES` method.
2036534ebe21SPeter Brune 
2037c3339decSBarry Smith   Logically Collective
2038534ebe21SPeter Brune 
2039534ebe21SPeter Brune   Input Parameters:
2040f6dfbefdSBarry Smith + snes         - the `SNES` context
2041365a6726SPeter Brune - normschedule - the type of the norm used
2042534ebe21SPeter Brune 
2043534ebe21SPeter Brune   Level: advanced
2044534ebe21SPeter Brune 
20451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2046534ebe21SPeter Brune @*/
2047d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2048d71ae5a4SJacob Faibussowitsch {
2049534ebe21SPeter Brune   PetscFunctionBegin;
2050534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2051365a6726SPeter Brune   *normschedule = snes->normschedule;
20523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2053534ebe21SPeter Brune }
2054534ebe21SPeter Brune 
2055c5ce4427SMatthew G. Knepley /*@
2056c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2057c5ce4427SMatthew G. Knepley 
2058c3339decSBarry Smith   Logically Collective
2059c5ce4427SMatthew G. Knepley 
2060c5ce4427SMatthew G. Knepley   Input Parameters:
2061f6dfbefdSBarry Smith + snes - the `SNES` context
2062f6dfbefdSBarry Smith - norm - the value of the norm
2063c5ce4427SMatthew G. Knepley 
2064c5ce4427SMatthew G. Knepley   Level: developer
2065c5ce4427SMatthew G. Knepley 
20661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2067c5ce4427SMatthew G. Knepley @*/
2068d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2069d71ae5a4SJacob Faibussowitsch {
2070c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2071c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2072c5ce4427SMatthew G. Knepley   snes->norm = norm;
20733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2074c5ce4427SMatthew G. Knepley }
2075c5ce4427SMatthew G. Knepley 
2076c5ce4427SMatthew G. Knepley /*@
2077c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2078c5ce4427SMatthew G. Knepley 
2079c5ce4427SMatthew G. Knepley   Not Collective
2080c5ce4427SMatthew G. Knepley 
2081c5ce4427SMatthew G. Knepley   Input Parameter:
2082f6dfbefdSBarry Smith . snes - the `SNES` context
2083c5ce4427SMatthew G. Knepley 
2084c5ce4427SMatthew G. Knepley   Output Parameter:
2085c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2086c5ce4427SMatthew G. Knepley 
2087c5ce4427SMatthew G. Knepley   Level: developer
2088c5ce4427SMatthew G. Knepley 
20891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2090c5ce4427SMatthew G. Knepley @*/
2091d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2092d71ae5a4SJacob Faibussowitsch {
2093c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2094c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20954f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2096c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2098c5ce4427SMatthew G. Knepley }
2099c5ce4427SMatthew G. Knepley 
2100c1e67a49SFande Kong /*@
2101f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2102c1e67a49SFande Kong 
2103c1e67a49SFande Kong   Not Collective
2104c1e67a49SFande Kong 
2105c1e67a49SFande Kong   Input Parameter:
2106f6dfbefdSBarry Smith . snes - the `SNES` context
2107c1e67a49SFande Kong 
2108c1e67a49SFande Kong   Output Parameter:
2109c1e67a49SFande Kong . ynorm - the last computed update norm
2110c1e67a49SFande Kong 
2111c1e67a49SFande Kong   Level: developer
2112c1e67a49SFande Kong 
2113f6dfbefdSBarry Smith   Note:
2114f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2115f6dfbefdSBarry Smith 
21161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2117c1e67a49SFande Kong @*/
2118d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2119d71ae5a4SJacob Faibussowitsch {
2120c1e67a49SFande Kong   PetscFunctionBegin;
2121c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21224f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2123c1e67a49SFande Kong   *ynorm = snes->ynorm;
21243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2125c1e67a49SFande Kong }
2126c1e67a49SFande Kong 
2127c1e67a49SFande Kong /*@
21284591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2129c1e67a49SFande Kong 
2130c1e67a49SFande Kong   Not Collective
2131c1e67a49SFande Kong 
2132c1e67a49SFande Kong   Input Parameter:
2133f6dfbefdSBarry Smith . snes - the `SNES` context
2134c1e67a49SFande Kong 
2135c1e67a49SFande Kong   Output Parameter:
2136c1e67a49SFande Kong . xnorm - the last computed solution norm
2137c1e67a49SFande Kong 
2138c1e67a49SFande Kong   Level: developer
2139c1e67a49SFande Kong 
21401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2141c1e67a49SFande Kong @*/
2142d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2143d71ae5a4SJacob Faibussowitsch {
2144c1e67a49SFande Kong   PetscFunctionBegin;
2145c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21464f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2147c1e67a49SFande Kong   *xnorm = snes->xnorm;
21483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2149c1e67a49SFande Kong }
2150c1e67a49SFande Kong 
2151cc4c1da9SBarry Smith /*@
2152f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2153f6dfbefdSBarry Smith   of the `SNES` method.
215447073ea2SPeter Brune 
2155c3339decSBarry Smith   Logically Collective
215647073ea2SPeter Brune 
215747073ea2SPeter Brune   Input Parameters:
2158f6dfbefdSBarry Smith + snes - the `SNES` context
2159f6dfbefdSBarry Smith - type - the function type
216047073ea2SPeter Brune 
216147073ea2SPeter Brune   Level: developer
216247073ea2SPeter Brune 
2163420bcc1bSBarry Smith   Values of the function type\:
2164f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2165f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2166f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2167f6dfbefdSBarry Smith 
2168420bcc1bSBarry Smith   Note:
2169f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2170f6dfbefdSBarry Smith 
21711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
217247073ea2SPeter Brune @*/
2173d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2174d71ae5a4SJacob Faibussowitsch {
217547073ea2SPeter Brune   PetscFunctionBegin;
217647073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
217747073ea2SPeter Brune   snes->functype = type;
21783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
217947073ea2SPeter Brune }
218047073ea2SPeter Brune 
2181cc4c1da9SBarry Smith /*@
2182f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
218347073ea2SPeter Brune   of the SNES method.
218447073ea2SPeter Brune 
2185c3339decSBarry Smith   Logically Collective
218647073ea2SPeter Brune 
218747073ea2SPeter Brune   Input Parameters:
2188f6dfbefdSBarry Smith + snes - the `SNES` context
2189f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
219047073ea2SPeter Brune 
219147073ea2SPeter Brune   Level: advanced
219247073ea2SPeter Brune 
21931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
219447073ea2SPeter Brune @*/
2195d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2196d71ae5a4SJacob Faibussowitsch {
219747073ea2SPeter Brune   PetscFunctionBegin;
219847073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
219947073ea2SPeter Brune   *type = snes->functype;
22003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2201534ebe21SPeter Brune }
2202534ebe21SPeter Brune 
2203c79ef259SPeter Brune /*@C
2204be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2205c79ef259SPeter Brune   use with composed nonlinear solvers.
2206c79ef259SPeter Brune 
2207c79ef259SPeter Brune   Input Parameters:
22089bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22098434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
221077e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2211c79ef259SPeter Brune 
2212dc4c0fb0SBarry Smith   Level: intermediate
2213dc4c0fb0SBarry Smith 
2214f6dfbefdSBarry Smith   Note:
2215f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2216f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2217c79ef259SPeter Brune 
22188434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2219c79ef259SPeter Brune @*/
22208434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2221d71ae5a4SJacob Faibussowitsch {
22226cab3a1bSJed Brown   DM dm;
22236cab3a1bSJed Brown 
2224646217ecSPeter Brune   PetscFunctionBegin;
22256cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22269566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22279566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2229646217ecSPeter Brune }
2230646217ecSPeter Brune 
2231bbc1464cSBarry Smith /*
2232bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2233bbc1464cSBarry Smith    changed during the KSPSolve()
2234bbc1464cSBarry Smith */
2235d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2236d71ae5a4SJacob Faibussowitsch {
2237bbc1464cSBarry Smith   DM     dm;
2238bbc1464cSBarry Smith   DMSNES sdm;
2239bbc1464cSBarry Smith 
2240bbc1464cSBarry Smith   PetscFunctionBegin;
22419566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22429566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2243bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2244bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2245792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22469566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22470df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2248ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2249792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22509566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2251bbc1464cSBarry Smith   } else {
2252792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22539566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2254bbc1464cSBarry Smith   }
22553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2256bbc1464cSBarry Smith }
2257bbc1464cSBarry Smith 
2258d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2259d71ae5a4SJacob Faibussowitsch {
2260e03ab78fSPeter Brune   DM     dm;
2261942e3340SBarry Smith   DMSNES sdm;
22626cab3a1bSJed Brown 
22638b0a5094SBarry Smith   PetscFunctionBegin;
22649566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22659566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22668b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2267bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2268792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22699566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2270792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22719566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2272bbc1464cSBarry Smith   } else {
2273792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22749566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2275bbc1464cSBarry Smith   }
22763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22778b0a5094SBarry Smith }
22788b0a5094SBarry Smith 
2279d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2280d71ae5a4SJacob Faibussowitsch {
22818b0a5094SBarry Smith   PetscFunctionBegin;
2282e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2283bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22849566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22859566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22878b0a5094SBarry Smith }
22888b0a5094SBarry Smith 
22898b0a5094SBarry Smith /*@C
22901d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22918b0a5094SBarry Smith 
2292c3339decSBarry Smith   Logically Collective
22938b0a5094SBarry Smith 
22948b0a5094SBarry Smith   Input Parameters:
2295f6dfbefdSBarry Smith + snes - the `SNES` context
2296dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
22978434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
229826a11704SBarry Smith . Amat - matrix with which $A(x) x - bp(x) - b$ is to be computed
2299dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
23008434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2301dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2302dc4c0fb0SBarry Smith 
2303dc4c0fb0SBarry Smith   Level: intermediate
23048b0a5094SBarry Smith 
23058b0a5094SBarry Smith   Notes:
230626a11704SBarry Smith   It is often better to provide the nonlinear function $F()$ and some approximation to its Jacobian directly and use
2307f450aa47SBarry 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.
2308f450aa47SBarry Smith 
2309f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23108b0a5094SBarry Smith 
23111d27aa22SBarry 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}$.
23121d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23138b0a5094SBarry Smith 
231426a11704SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using $A(x^{n})$ to construct the preconditioner.
23158b0a5094SBarry Smith 
23160d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23171d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23188b0a5094SBarry Smith 
23198b0a5094SBarry 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
23201d27aa22SBarry 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
23211d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23228b0a5094SBarry Smith 
23231d27aa22SBarry 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
232426a11704SBarry Smith   $A(x^{n})$ is used to build the preconditioner
23256b7fb656SBarry Smith 
232615229ffcSPierre 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.
23276b7fb656SBarry Smith 
2328dc4c0fb0SBarry 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
232926a11704SBarry 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
233026a11704SBarry 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`.
2331aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2332bbc1464cSBarry Smith 
23339bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23348434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23358b0a5094SBarry Smith @*/
23368434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2337d71ae5a4SJacob Faibussowitsch {
2338e03ab78fSPeter Brune   DM dm;
2339e03ab78fSPeter Brune 
23408b0a5094SBarry Smith   PetscFunctionBegin;
23418b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23429566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23439566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23449566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23459566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23469566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23488b0a5094SBarry Smith }
23498b0a5094SBarry Smith 
23507971a8bfSPeter Brune /*@C
23517971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23527971a8bfSPeter Brune 
2353f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23547971a8bfSPeter Brune 
23557971a8bfSPeter Brune   Input Parameter:
2356f6dfbefdSBarry Smith . snes - the `SNES` context
23577971a8bfSPeter Brune 
2358d8d19677SJose E. Roman   Output Parameters:
2359dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23608434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2361dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2362dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23638434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2364dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23657971a8bfSPeter Brune 
23667971a8bfSPeter Brune   Level: advanced
23677971a8bfSPeter Brune 
23688434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23697971a8bfSPeter Brune @*/
23708434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2371d71ae5a4SJacob Faibussowitsch {
23727971a8bfSPeter Brune   DM dm;
23737971a8bfSPeter Brune 
23747971a8bfSPeter Brune   PetscFunctionBegin;
23757971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23769566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23779566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23789566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23799566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23817971a8bfSPeter Brune }
23827971a8bfSPeter Brune 
2383d25893d9SBarry Smith /*@C
2384dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2385d25893d9SBarry Smith 
2386c3339decSBarry Smith   Logically Collective
2387d25893d9SBarry Smith 
2388d25893d9SBarry Smith   Input Parameters:
2389f6dfbefdSBarry Smith + snes - the `SNES` context
23908434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2391d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2392dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2393d25893d9SBarry Smith 
2394d25893d9SBarry Smith   Level: intermediate
2395d25893d9SBarry Smith 
23968434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2397d25893d9SBarry Smith @*/
23988434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2399d71ae5a4SJacob Faibussowitsch {
2400d25893d9SBarry Smith   PetscFunctionBegin;
2401d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2402d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2403d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
24043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2405d25893d9SBarry Smith }
2406d25893d9SBarry Smith 
24071096aae1SMatthew Knepley /*@C
2408dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2409dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
24101096aae1SMatthew Knepley 
2411c3339decSBarry Smith   Logically Collective
24121096aae1SMatthew Knepley 
24131096aae1SMatthew Knepley   Input Parameter:
2414f6dfbefdSBarry Smith . snes - the `SNES` context
24151096aae1SMatthew Knepley 
24161096aae1SMatthew Knepley   Output Parameter:
2417dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24181096aae1SMatthew Knepley 
24191096aae1SMatthew Knepley   Level: intermediate
24201096aae1SMatthew Knepley 
24211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24221096aae1SMatthew Knepley @*/
2423d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2424d71ae5a4SJacob Faibussowitsch {
24251096aae1SMatthew Knepley   PetscFunctionBegin;
24260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24274f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
242885385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24301096aae1SMatthew Knepley }
24311096aae1SMatthew Knepley 
24329b94acceSBarry Smith /*@
2433f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24349b94acceSBarry Smith 
2435c3339decSBarry Smith   Collective
2436c7afd0dbSLois Curfman McInnes 
24379b94acceSBarry Smith   Input Parameters:
2438f6dfbefdSBarry Smith + snes - the `SNES` context
2439c7afd0dbSLois Curfman McInnes - x    - input vector
24409b94acceSBarry Smith 
24419b94acceSBarry Smith   Output Parameter:
2442f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24439b94acceSBarry Smith 
2444dc4c0fb0SBarry Smith   Level: developer
2445dc4c0fb0SBarry Smith 
244600677de2SStefano Zampini   Notes:
2447f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2448bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
244936851e7fSLois Curfman McInnes 
245000677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
245100677de2SStefano Zampini 
24521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24539b94acceSBarry Smith @*/
2454d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2455d71ae5a4SJacob Faibussowitsch {
24566cab3a1bSJed Brown   DM     dm;
2457942e3340SBarry Smith   DMSNES sdm;
24589b94acceSBarry Smith 
24593a40ed3dSBarry Smith   PetscFunctionBegin;
24600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24610700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24620700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2463c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2464c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2465e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2466184914b5SBarry Smith 
24679566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24689566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24690fdf79fbSJacob 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().");
247032f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
247148a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24729566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24738ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24748ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2475800f99ffSJeremy L Thompson     {
2476800f99ffSJeremy L Thompson       void           *ctx;
24778434afd1SBarry Smith       SNESFunctionFn *computefunction;
2478800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2479800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2480800f99ffSJeremy L Thompson     }
24819566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
248248a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24830fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24849566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24850fdf79fbSJacob Faibussowitsch   }
24861baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2487ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2488422a814eSBarry Smith   /*
2489422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2490422a814eSBarry Smith      propagate the value to all processes
2491422a814eSBarry Smith   */
2492f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
24933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24949b94acceSBarry Smith }
24959b94acceSBarry Smith 
2496c79ef259SPeter Brune /*@
24970b4b7b1cSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`.
2498bbc1464cSBarry Smith 
2499c3339decSBarry Smith   Collective
2500bbc1464cSBarry Smith 
2501bbc1464cSBarry Smith   Input Parameters:
2502f6dfbefdSBarry Smith + snes - the `SNES` context
2503bbc1464cSBarry Smith - x    - input vector
2504bbc1464cSBarry Smith 
2505bbc1464cSBarry Smith   Output Parameter:
25060b4b7b1cSBarry Smith . y - output vector
2507bbc1464cSBarry Smith 
2508dc4c0fb0SBarry Smith   Level: developer
2509dc4c0fb0SBarry Smith 
2510bbc1464cSBarry Smith   Notes:
2511420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2512bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2513bbc1464cSBarry Smith 
2514dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2515f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2516dd8e379bSPierre 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.
2517bbc1464cSBarry Smith 
25180b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()`
2519bbc1464cSBarry Smith @*/
2520d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2521d71ae5a4SJacob Faibussowitsch {
2522bbc1464cSBarry Smith   DM     dm;
2523bbc1464cSBarry Smith   DMSNES sdm;
2524bbc1464cSBarry Smith 
2525bbc1464cSBarry Smith   PetscFunctionBegin;
2526bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2527bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2528bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2529bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2530bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2531e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2532bbc1464cSBarry Smith 
25339566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25349566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25369566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2537bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2538bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2539792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25409566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2542bbc1464cSBarry Smith   snes->nfuncs++;
2543bbc1464cSBarry Smith   /*
2544bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2545bbc1464cSBarry Smith      propagate the value to all processes
2546bbc1464cSBarry Smith   */
2547f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2549bbc1464cSBarry Smith }
2550bbc1464cSBarry Smith 
2551bbc1464cSBarry Smith /*@
2552f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2553c79ef259SPeter Brune 
2554c3339decSBarry Smith   Collective
2555c79ef259SPeter Brune 
2556c79ef259SPeter Brune   Input Parameters:
2557f6dfbefdSBarry Smith + snes - the `SNES` context
2558c79ef259SPeter Brune . x    - input vector
2559c79ef259SPeter Brune - b    - rhs vector
2560c79ef259SPeter Brune 
2561c79ef259SPeter Brune   Output Parameter:
2562c79ef259SPeter Brune . x - new solution vector
2563c79ef259SPeter Brune 
2564dc4c0fb0SBarry Smith   Level: developer
2565dc4c0fb0SBarry Smith 
2566f6dfbefdSBarry Smith   Note:
2567f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2568c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2569c79ef259SPeter Brune   themselves.
2570c79ef259SPeter Brune 
25718434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2572c79ef259SPeter Brune @*/
2573d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2574d71ae5a4SJacob Faibussowitsch {
25756cab3a1bSJed Brown   DM     dm;
2576942e3340SBarry Smith   DMSNES sdm;
2577646217ecSPeter Brune 
2578646217ecSPeter Brune   PetscFunctionBegin;
2579646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2580064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2581064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2582064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2583064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2584e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25869566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25879566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25880fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25899566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2590792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25919566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2594646217ecSPeter Brune }
2595646217ecSPeter Brune 
2596494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2597494a190aSStefano Zampini {
2598494a190aSStefano Zampini   Vec          X;
2599494a190aSStefano Zampini   PetscScalar *g;
2600494a190aSStefano Zampini   PetscReal    f, f2;
2601494a190aSStefano Zampini   PetscInt     low, high, N, i;
2602494a190aSStefano Zampini   PetscBool    flg;
2603494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2604494a190aSStefano Zampini 
2605494a190aSStefano Zampini   PetscFunctionBegin;
2606494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2607494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2608494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2609494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2610494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2611494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2612494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2613494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2614494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2615494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2616494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2617494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2618494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2619494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2620494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2621494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2622494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2623494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2624494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2625494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2626494a190aSStefano Zampini   }
2627494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2628494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2629494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2630494a190aSStefano Zampini }
2631494a190aSStefano Zampini 
2632*1dfd7622SMatthew Knepley /*@
2633*1dfd7622SMatthew Knepley   SNESTestFunction - Computes the difference between the computed and finite-difference functions
2634*1dfd7622SMatthew Knepley 
2635*1dfd7622SMatthew Knepley   Collective
2636*1dfd7622SMatthew Knepley 
2637*1dfd7622SMatthew Knepley   Input Parameters:
2638*1dfd7622SMatthew Knepley . snes - the `SNES` context
2639*1dfd7622SMatthew Knepley 
2640*1dfd7622SMatthew Knepley   Options Database Keys:
2641*1dfd7622SMatthew Knepley + -snes_test_function      - compare the user provided function with one compute via finite differences to check for errors.
2642*1dfd7622SMatthew Knepley - -snes_test_function_view - display the user provided function, the finite difference function and the difference
2643*1dfd7622SMatthew Knepley 
2644*1dfd7622SMatthew Knepley   Level: developer
2645*1dfd7622SMatthew Knepley 
2646*1dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestJacobian()`, `SNESSetFunction()`, `SNESComputeFunction()`
2647*1dfd7622SMatthew Knepley @*/
2648494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2649494a190aSStefano Zampini {
2650494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2651*1dfd7622SMatthew Knepley   PetscBool         complete_print = PETSC_FALSE;
2652494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2653494a190aSStefano Zampini   PetscScalar       dot;
2654494a190aSStefano Zampini   MPI_Comm          comm;
2655494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2656494a190aSStefano Zampini   PetscViewerFormat format;
2657494a190aSStefano Zampini   PetscInt          tabs;
2658494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26598434afd1SBarry Smith   SNESObjectiveFn  *objective;
2660494a190aSStefano Zampini 
2661494a190aSStefano Zampini   PetscFunctionBegin;
2662494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2663494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2664494a190aSStefano Zampini 
2665494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2666494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2667494a190aSStefano Zampini   PetscOptionsEnd();
2668494a190aSStefano Zampini 
2669494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2670494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2671494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2672494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2673494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2674494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2675494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2676494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2677494a190aSStefano Zampini   }
2678494a190aSStefano Zampini   if (!directionsprinted) {
2679494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2680494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2681494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2682494a190aSStefano Zampini   }
2683494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2684494a190aSStefano Zampini 
2685494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2686494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2687494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2688494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2689494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2690494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2691494a190aSStefano Zampini 
2692494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2693494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2694494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2695494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2696494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2697494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2698494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2699494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2700494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2701494a190aSStefano 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))));
2702494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2703494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2704494a190aSStefano Zampini 
2705494a190aSStefano Zampini   if (complete_print) {
2706494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2707494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2708494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2709494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2710494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2711494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2712494a190aSStefano Zampini   }
2713494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2714494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2715494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2716494a190aSStefano Zampini 
2717494a190aSStefano Zampini   if (complete_print) {
2718494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2719494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2720494a190aSStefano Zampini   }
2721494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2722494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2723494a190aSStefano Zampini }
2724494a190aSStefano Zampini 
2725cbf8f02cSMatthew G. Knepley /*@
2726cbf8f02cSMatthew G. Knepley   SNESTestJacobian - Computes the difference between the computed and finite-difference Jacobians
2727cbf8f02cSMatthew G. Knepley 
2728cbf8f02cSMatthew G. Knepley   Collective
2729cbf8f02cSMatthew G. Knepley 
2730cbf8f02cSMatthew G. Knepley   Input Parameters:
2731cbf8f02cSMatthew G. Knepley . snes - the `SNES` context
2732cbf8f02cSMatthew G. Knepley 
2733cbf8f02cSMatthew G. Knepley   Output Parameters:
2734*1dfd7622SMatthew Knepley + Jnorm    - the Frobenius norm of the computed Jacobian, or `NULL`
2735*1dfd7622SMatthew Knepley - diffNorm - the Frobenius norm of the difference of the computed and finite-difference Jacobians, or `NULL`
2736cbf8f02cSMatthew G. Knepley 
2737cbf8f02cSMatthew G. Knepley   Options Database Keys:
2738cbf8f02cSMatthew 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.
2739cbf8f02cSMatthew G. Knepley - -snes_test_jacobian_view                 - display the user provided Jacobian, the finite difference Jacobian and the difference
2740cbf8f02cSMatthew G. Knepley 
2741cbf8f02cSMatthew G. Knepley   Level: developer
2742cbf8f02cSMatthew G. Knepley 
2743*1dfd7622SMatthew Knepley   Note:
2744*1dfd7622SMatthew Knepley   Directions and norms are printed to stdout if `diffNorm` is `NULL`.
2745*1dfd7622SMatthew Knepley 
2746*1dfd7622SMatthew Knepley .seealso: [](ch_snes), `SNESTestFunction()`, `SNESSetJacobian()`, `SNESComputeJacobian()`
2747cbf8f02cSMatthew G. Knepley @*/
2748cbf8f02cSMatthew G. Knepley PetscErrorCode SNESTestJacobian(SNES snes, PetscReal *Jnorm, PetscReal *diffNorm)
2749d71ae5a4SJacob Faibussowitsch {
275012837594SBarry Smith   Mat               A, B, C, D, jacobian;
27514df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2752e885f1abSBarry Smith   PetscReal         nrm, gnorm;
275381e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27540e276705SLisandro Dalcin   MatType           mattype;
2755e885f1abSBarry Smith   PetscInt          m, n, M, N;
2756e885f1abSBarry Smith   void             *functx;
2757*1dfd7622SMatthew Knepley   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, flg, istranspose;
2758*1dfd7622SMatthew Knepley   PetscBool         silent = diffNorm != PETSC_NULLPTR ? PETSC_TRUE : PETSC_FALSE;
27593325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2760e885f1abSBarry Smith   MPI_Comm          comm;
2761e885f1abSBarry Smith   PetscInt          tabs;
276212837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27633325ff46SBarry Smith   PetscViewerFormat format;
2764e885f1abSBarry Smith 
2765e885f1abSBarry Smith   PetscFunctionBegin;
2766d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27694ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27719566063dSJacob 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));
2772d0609cedSBarry Smith   PetscOptionsEnd();
2773e885f1abSBarry Smith 
27749566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27759566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27769566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27779566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2778*1dfd7622SMatthew Knepley   if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
2779*1dfd7622SMatthew Knepley   if (!complete_print && !silent && !directionsprinted) {
27809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
278212837594SBarry Smith   }
2783*1dfd7622SMatthew Knepley   if (!directionsprinted && !silent) {
27849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
27859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
278612837594SBarry Smith     directionsprinted = PETSC_TRUE;
2787e885f1abSBarry Smith   }
27881baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2789e885f1abSBarry Smith 
27909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
279112837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
279212837594SBarry Smith   else jacobian = snes->jacobian_pre;
279312837594SBarry Smith 
27944df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
27954df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
27969566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
27974df93895SStefano Zampini 
2798a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
27999566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
28009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
28019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
280212837594SBarry Smith   while (jacobian) {
28032cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
28042cd624f9SStefano Zampini 
28052cd624f9SStefano Zampini     if (istranspose) {
28069566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
28072cd624f9SStefano Zampini       Jsave    = jacobian;
28082cd624f9SStefano Zampini       jacobian = JT;
28092cd624f9SStefano Zampini     }
28109566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
281112837594SBarry Smith     if (flg) {
281212837594SBarry Smith       A = jacobian;
28139566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
281412837594SBarry Smith     } else {
28159566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
281612837594SBarry Smith     }
2817e885f1abSBarry Smith 
28189566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
28199566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
28209566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
28219566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
28229566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
28239566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
28249566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
28259566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
28269566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2827e885f1abSBarry Smith 
28289566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28299566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
283012837594SBarry Smith 
28319566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28329566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28339566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28349566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28359566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
283612837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
2837*1dfd7622SMatthew Knepley     if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
2838e885f1abSBarry Smith     if (complete_print) {
28399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
28409566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
28419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
28429566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2843e885f1abSBarry Smith     }
2844e885f1abSBarry Smith 
2845df10fb39SFande Kong     if (threshold_print || complete_print) {
2846e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2847e885f1abSBarry Smith       PetscScalar       *cvals;
2848e885f1abSBarry Smith       const PetscInt    *bcols;
2849e885f1abSBarry Smith       const PetscScalar *bvals;
2850e885f1abSBarry Smith 
28519566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28529566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28539566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28549566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28559566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28569566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28570e276705SLisandro Dalcin 
28589566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28599566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2860e885f1abSBarry Smith 
2861e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28629566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28639566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2864e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
286523a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2866e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2867e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2868e885f1abSBarry Smith             cncols += 1;
2869e885f1abSBarry Smith           }
2870e885f1abSBarry Smith         }
287148a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28729566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28739566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2874e885f1abSBarry Smith       }
28759566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28769566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28779566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28789566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28799566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2880e885f1abSBarry Smith     }
28819566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
28829566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
28839566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
28842cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
288512837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
288612837594SBarry Smith       jacobian = snes->jacobian_pre;
2887*1dfd7622SMatthew Knepley       if (!silent) PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
28889371c9d4SSatish Balay     } else jacobian = NULL;
288912837594SBarry Smith   }
28909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
28911baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2892648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
28939566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2894cbf8f02cSMatthew G. Knepley 
2895cbf8f02cSMatthew G. Knepley   if (Jnorm) *Jnorm = gnorm;
2896cbf8f02cSMatthew G. Knepley   if (diffNorm) *diffNorm = nrm;
28973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2898e885f1abSBarry Smith }
2899e885f1abSBarry Smith 
290062fef451SLois Curfman McInnes /*@
2901f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
290262fef451SLois Curfman McInnes 
2903c3339decSBarry Smith   Collective
2904c7afd0dbSLois Curfman McInnes 
290562fef451SLois Curfman McInnes   Input Parameters:
2906f6dfbefdSBarry Smith + snes - the `SNES` context
2907e4094ef1SJacob Faibussowitsch - X    - input vector
290862fef451SLois Curfman McInnes 
290962fef451SLois Curfman McInnes   Output Parameters:
2910c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2911420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2912fee21e36SBarry Smith 
2913e35cf81dSBarry Smith   Options Database Keys:
291467b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
291567b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2916455a5933SJed 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.
2917455a5933SJed 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
2918693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2919693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2920693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
29217addb90fSBarry Smith . -snes_compare_operator                   - Make the comparison options above use the operator instead of the matrix used to construct the preconditioner
292294d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2923a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2924c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2925dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2926dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2927a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2928a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2929c01495d3SJed Brown 
2930dc4c0fb0SBarry Smith   Level: developer
2931dc4c0fb0SBarry Smith 
2932f6dfbefdSBarry Smith   Note:
293362fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
293462fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
293562fef451SLois Curfman McInnes 
2936420bcc1bSBarry Smith   Developer Note:
2937dc4c0fb0SBarry 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
2938420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2939e885f1abSBarry Smith 
29401cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
294162fef451SLois Curfman McInnes @*/
2942d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2943d71ae5a4SJacob Faibussowitsch {
2944ace3abfcSBarry Smith   PetscBool flag;
29456cab3a1bSJed Brown   DM        dm;
2946942e3340SBarry Smith   DMSNES    sdm;
2947e0e3a89bSBarry Smith   KSP       ksp;
29483a40ed3dSBarry Smith 
29493a40ed3dSBarry Smith   PetscFunctionBegin;
29500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29510700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2952c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2953e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29549566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29559566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29563232da50SPeter Brune 
295701c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2958fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2959fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2960f5af7f23SKarl Rupp 
29619566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2962fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29639566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29649566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2965ebd3b9afSBarry Smith     if (flag) {
29669566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29679566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2968ebd3b9afSBarry Smith     }
29693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
297037ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
297163a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29729566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2973ebd3b9afSBarry Smith     if (flag) {
29749566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29759566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2976ebd3b9afSBarry Smith     }
29773ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2978e35cf81dSBarry Smith   }
2979efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29809566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29819566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29823ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2983d728fb7dSPeter Brune   }
2984e35cf81dSBarry Smith 
29859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
29869566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2987800f99ffSJeremy L Thompson   {
2988800f99ffSJeremy L Thompson     void           *ctx;
29898434afd1SBarry Smith     SNESJacobianFn *J;
2990800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2991800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2992800f99ffSJeremy L Thompson   }
29939566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
29949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
299528d58a37SPierre Jolivet 
29967addb90fSBarry Smith   /* attach latest linearization point to the matrix used to construct the preconditioner */
29979566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2998a8054027SBarry Smith 
2999e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
30009566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
30013b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
30029566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
30039566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
30043b4f5425SBarry Smith     snes->lagpreconditioner = -1;
30053b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
30069566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
30079566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
300837ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
300963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
30109566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
3011d1e9a80fSBarry Smith   } else {
30129566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
30139566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
3014a8054027SBarry Smith   }
3015a8054027SBarry Smith 
30164df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
30174df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
30184df93895SStefano Zampini   {
30194df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
30204df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
30214df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
30224df93895SStefano Zampini 
30234df93895SStefano Zampini     snes->vec_sol      = X;
30244df93895SStefano Zampini     snes->jacobian     = A;
30254df93895SStefano Zampini     snes->jacobian_pre = B;
3026*1dfd7622SMatthew Knepley     if (snes->testFunc) PetscCall(SNESTestFunction(snes));
3027*1dfd7622SMatthew Knepley     if (snes->testJac) PetscCall(SNESTestJacobian(snes, NULL, NULL));
3028494a190aSStefano Zampini 
30294df93895SStefano Zampini     snes->vec_sol      = xsave;
30304df93895SStefano Zampini     snes->jacobian     = jacobiansave;
30314df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
30324df93895SStefano Zampini   }
30334df93895SStefano Zampini 
3034693365a8SJed Brown   {
3035693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3036648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3037648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3038648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3039648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3040693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
30410298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
3042693365a8SJed Brown       PetscViewer vdraw, vstdout;
30436b3a5b13SJed Brown       PetscBool   flg;
3044693365a8SJed Brown       if (flag_operator) {
30459566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3046693365a8SJed Brown         Bexp = Bexp_mine;
3047693365a8SJed Brown       } else {
30487addb90fSBarry Smith         /* See if the matrix used to construct the preconditioner can be viewed and added directly */
30499566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
305094ab13aaSBarry Smith         if (flg) Bexp = B;
3051693365a8SJed Brown         else {
3052693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30539566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3054693365a8SJed Brown           Bexp = Bexp_mine;
3055693365a8SJed Brown         }
3056693365a8SJed Brown       }
30579566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30589566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3060693365a8SJed Brown       if (flag_draw || flag_contour) {
30619566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30629566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30630298fd71SBarry Smith       } else vdraw = NULL;
30649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30659566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30669566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30689566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30699566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30709566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30729566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3073693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30749566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30759566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30769566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3077693365a8SJed Brown       }
30789566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30799566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30809566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30819566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3082693365a8SJed Brown     }
3083693365a8SJed Brown   }
30844c30e9fbSJed Brown   {
30856719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
30866719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3087648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3088648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3089648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3090648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3091648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
309227b0f280SBarry Smith     if (flag_threshold) {
30939566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
30949566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
309527b0f280SBarry Smith     }
30966719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
30974c30e9fbSJed Brown       Mat             Bfd;
30984c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3099335efc43SPeter Brune       MatColoring     coloring;
31004c30e9fbSJed Brown       ISColoring      iscoloring;
31014c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
31028434afd1SBarry Smith       SNESFunctionFn *func;
31034c30e9fbSJed Brown       void           *funcctx;
31046719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
31054c30e9fbSJed Brown 
31069566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
31079566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
31089566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
31099566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
31109566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
31119566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
31129566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
31139566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31149566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
31159566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
31164c30e9fbSJed Brown 
31174c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
31189566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
31192ba42892SBarry Smith       PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)func, funcctx));
31209566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
31219566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
31229566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
31239566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
31249566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
31254c30e9fbSJed Brown 
31269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
31274c30e9fbSJed Brown       if (flag_draw || flag_contour) {
31289566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31299566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31300298fd71SBarry Smith       } else vdraw = NULL;
31319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31329566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
31339566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
31349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31359566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31369566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
31379566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31389566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31399566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31409566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31429566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31434c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
31449566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31459566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
31469566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
31474c30e9fbSJed Brown       }
31489566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31496719d8e4SJed Brown 
31506719d8e4SJed Brown       if (flag_threshold) {
31516719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31529566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31539566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31546719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31556719d8e4SJed Brown           const PetscScalar *ba, *ca;
31566719d8e4SJed Brown           const PetscInt    *bj, *cj;
31576719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31586719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31599566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31609566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31615f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31626719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31636719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31646719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31656719d8e4SJed Brown               maxentrycol = bj[j];
31666719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31676719d8e4SJed Brown             }
31686719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31696719d8e4SJed Brown               maxdiffcol = bj[j];
31706719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31716719d8e4SJed Brown             }
31726719d8e4SJed Brown             if (rdiff > maxrdiff) {
31736719d8e4SJed Brown               maxrdiffcol = bj[j];
31746719d8e4SJed Brown               maxrdiff    = rdiff;
31756719d8e4SJed Brown             }
31766719d8e4SJed Brown           }
31776719d8e4SJed Brown           if (maxrdiff > 1) {
317863a3b9bcSJacob 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));
31796719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31806719d8e4SJed Brown               PetscReal rdiff;
31816719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
318248a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
31836719d8e4SJed Brown             }
318463a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
31856719d8e4SJed Brown           }
31869566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
31879566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
31886719d8e4SJed Brown         }
31896719d8e4SJed Brown       }
31909566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
31919566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
31924c30e9fbSJed Brown     }
31934c30e9fbSJed Brown   }
31943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31959b94acceSBarry Smith }
31969b94acceSBarry Smith 
31979b94acceSBarry Smith /*@C
31989b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3199044dda88SLois Curfman McInnes   location to store the matrix.
32009b94acceSBarry Smith 
3201c3339decSBarry Smith   Logically Collective
3202c7afd0dbSLois Curfman McInnes 
32039b94acceSBarry Smith   Input Parameters:
3204f6dfbefdSBarry Smith + snes - the `SNES` context
3205e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3206dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
32078434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3208c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3209dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3210dc4c0fb0SBarry Smith 
3211dc4c0fb0SBarry Smith   Level: beginner
32129b94acceSBarry Smith 
32139b94acceSBarry Smith   Notes:
3214dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
321516913363SBarry Smith   each matrix.
321616913363SBarry Smith 
3217dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3218dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3219895c21f2SBarry Smith 
3220dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3221f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3222a8a26c1eSJed Brown 
3223c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3224f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3225c3cc8fd1SJed Brown 
32261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
32278434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32289b94acceSBarry Smith @*/
32298434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3230d71ae5a4SJacob Faibussowitsch {
32316cab3a1bSJed Brown   DM dm;
32323a7fca6bSBarry Smith 
32333a40ed3dSBarry Smith   PetscFunctionBegin;
32340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3235e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3236e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3237e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3238e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32399566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32409566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3241e5d3d808SBarry Smith   if (Amat) {
32429566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
32439566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3244f5af7f23SKarl Rupp 
3245e5d3d808SBarry Smith     snes->jacobian = Amat;
32463a7fca6bSBarry Smith   }
3247e5d3d808SBarry Smith   if (Pmat) {
32489566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
32499566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3250f5af7f23SKarl Rupp 
3251e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32523a7fca6bSBarry Smith   }
32533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32549b94acceSBarry Smith }
325562fef451SLois Curfman McInnes 
3256c2aafc4cSSatish Balay /*@C
3257b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3258b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3259b4fd4287SBarry Smith 
3260420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3261c7afd0dbSLois Curfman McInnes 
3262b4fd4287SBarry Smith   Input Parameter:
3263b4fd4287SBarry Smith . snes - the nonlinear solver context
3264b4fd4287SBarry Smith 
3265b4fd4287SBarry Smith   Output Parameters:
3266dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3267dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32688434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3269dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3270fee21e36SBarry Smith 
327136851e7fSLois Curfman McInnes   Level: advanced
327236851e7fSLois Curfman McInnes 
32738434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3274b4fd4287SBarry Smith @*/
32758434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3276d71ae5a4SJacob Faibussowitsch {
32776cab3a1bSJed Brown   DM dm;
32786cab3a1bSJed Brown 
32793a40ed3dSBarry Smith   PetscFunctionBegin;
32800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3281e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3282e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
32839566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3284800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
32853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3286b4fd4287SBarry Smith }
3287b4fd4287SBarry Smith 
3288d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3289d71ae5a4SJacob Faibussowitsch {
329058b371f3SBarry Smith   DM     dm;
329158b371f3SBarry Smith   DMSNES sdm;
329258b371f3SBarry Smith 
329358b371f3SBarry Smith   PetscFunctionBegin;
32949566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32959566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
329658b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
329758b371f3SBarry Smith     DM        dm;
329858b371f3SBarry Smith     PetscBool isdense, ismf;
329958b371f3SBarry Smith 
33009566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33019566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
33029566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
330358b371f3SBarry Smith     if (isdense) {
33049566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
330558b371f3SBarry Smith     } else if (!ismf) {
33069566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
330758b371f3SBarry Smith     }
330858b371f3SBarry Smith   }
33093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
331058b371f3SBarry Smith }
331158b371f3SBarry Smith 
33129b94acceSBarry Smith /*@
33139b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
33140b4b7b1cSBarry Smith   of a nonlinear solver `SNESSolve()`.
33159b94acceSBarry Smith 
3316c3339decSBarry Smith   Collective
3317fee21e36SBarry Smith 
33182fe279fdSBarry Smith   Input Parameter:
3319f6dfbefdSBarry Smith . snes - the `SNES` context
3320c7afd0dbSLois Curfman McInnes 
3321dc4c0fb0SBarry Smith   Level: advanced
3322dc4c0fb0SBarry Smith 
3323f6dfbefdSBarry Smith   Note:
33240b4b7b1cSBarry Smith   For basic use of the `SNES` solvers the user does not need to explicitly call
3325f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3326f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3327f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3328f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3329272ac6f2SLois Curfman McInnes 
33300b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()`
33319b94acceSBarry Smith @*/
3332d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3333d71ae5a4SJacob Faibussowitsch {
33346cab3a1bSJed Brown   DM             dm;
3335942e3340SBarry Smith   DMSNES         sdm;
3336c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
33376e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
33389b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
33399b5c1c08SStefano Zampini   Vec            f, fpc;
33409b5c1c08SStefano Zampini   void          *funcctx;
33419b5c1c08SStefano Zampini   void          *jacctx, *appctx;
33429b5c1c08SStefano Zampini   Mat            j, jpre;
33436b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33446b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33458434afd1SBarry Smith   SNESFunctionFn *func;
33468434afd1SBarry Smith   SNESJacobianFn *jac;
33473a40ed3dSBarry Smith 
33483a40ed3dSBarry Smith   PetscFunctionBegin;
33490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33503ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3351fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33529b94acceSBarry Smith 
335348a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
335485385478SLisandro Dalcin 
33559566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
335658c9b817SLisandro Dalcin 
33579566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33589566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33599566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
336058b371f3SBarry Smith 
336148a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3362efd51863SBarry Smith 
336348a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3364b710008aSBarry Smith 
3365d8d34be6SBarry Smith   if (snes->linesearch) {
33669566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33679566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3368d8d34be6SBarry Smith   }
33699e764e56SPeter Brune 
33709b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3371b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3372172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3373172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3374172a4300SPeter Brune   }
3375d8f46077SPeter Brune 
3376efd4aadfSBarry Smith   if (snes->npc) {
33776e2a1849SPeter Brune     /* copy the DM over */
33789566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33799566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33806e2a1849SPeter Brune 
33819566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33829566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
33839566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
33849566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
33859566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
33869566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
33879566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
33889b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
33899566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
33906e2a1849SPeter Brune 
33916e2a1849SPeter Brune     /* copy the function pointers over */
33929566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
33936e2a1849SPeter Brune 
33946e2a1849SPeter Brune     /* default to 1 iteration */
33959566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3396efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
33979566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3398a9936a0cSPeter Brune     } else {
33999566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3400a9936a0cSPeter Brune     }
34019566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
34026e2a1849SPeter Brune 
34036e2a1849SPeter Brune     /* copy the line search context over */
3404d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
34059566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
34069566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
34079566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
34089566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
34099566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
34109566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
34119566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
34126e2a1849SPeter Brune     }
3413d8d34be6SBarry Smith   }
34141baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
3415835f2295SStefano Zampini   if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, &snes->ctx));
34166e2a1849SPeter Brune 
341737ec4e1aSPeter Brune   snes->jac_iter = 0;
341837ec4e1aSPeter Brune   snes->pre_iter = 0;
341937ec4e1aSPeter Brune 
3420dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
342158c9b817SLisandro Dalcin 
34229566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
342358b371f3SBarry Smith 
3424b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
34256c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3426d8d34be6SBarry Smith       if (snes->linesearch) {
34279566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
34289566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34296c67d002SPeter Brune       }
34306c67d002SPeter Brune     }
3431d8d34be6SBarry Smith   }
3432fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34337aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
34343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34359b94acceSBarry Smith }
34369b94acceSBarry Smith 
343737596af1SLisandro Dalcin /*@
34380b4b7b1cSBarry 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
343937596af1SLisandro Dalcin 
3440c3339decSBarry Smith   Collective
344137596af1SLisandro Dalcin 
344237596af1SLisandro Dalcin   Input Parameter:
34430b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
344437596af1SLisandro Dalcin 
3445d25893d9SBarry Smith   Level: intermediate
3446d25893d9SBarry Smith 
344795452b02SPatrick Sanan   Notes:
34480b4b7b1cSBarry Smith   Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain.
34490b4b7b1cSBarry Smith 
3450f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
345137596af1SLisandro Dalcin 
3452f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3453f6dfbefdSBarry Smith 
34541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
345537596af1SLisandro Dalcin @*/
3456d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3457d71ae5a4SJacob Faibussowitsch {
345837596af1SLisandro Dalcin   PetscFunctionBegin;
345937596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
346049abdd8aSBarry Smith   if (snes->ops->ctxdestroy && snes->ctx) {
3461835f2295SStefano Zampini     PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)(&snes->ctx));
346249abdd8aSBarry Smith     snes->ctx = NULL;
3463d25893d9SBarry Smith   }
34641baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34658a23116dSBarry Smith 
3466dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34671baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34689e764e56SPeter Brune 
34691baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34709e764e56SPeter Brune 
34719566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34729566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34739566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34749566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34759566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34769566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34789566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34799566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3480f5af7f23SKarl Rupp 
348140fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
348240fdac6aSLawrence Mitchell 
348337596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
348437596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
34853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
348637596af1SLisandro Dalcin }
348737596af1SLisandro Dalcin 
348852baeb72SSatish Balay /*@
348936d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
349036d43d94SBarry Smith   removes the default viewer.
3491c4421ceaSFande Kong 
3492c3339decSBarry Smith   Collective
3493c4421ceaSFande Kong 
3494c4421ceaSFande Kong   Input Parameter:
34950b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
3496c4421ceaSFande Kong 
3497c4421ceaSFande Kong   Level: intermediate
3498c4421ceaSFande Kong 
3499420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3500c4421ceaSFande Kong @*/
3501d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3502d71ae5a4SJacob Faibussowitsch {
3503c4421ceaSFande Kong   PetscInt i;
3504c4421ceaSFande Kong 
3505c4421ceaSFande Kong   PetscFunctionBegin;
3506c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3507c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
350848a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3509c4421ceaSFande Kong   }
3510c4421ceaSFande Kong   snes->numberreasonviews = 0;
3511648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
35123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3513c4421ceaSFande Kong }
3514c4421ceaSFande Kong 
35150764c050SBarry Smith /*@
35169b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3517f6dfbefdSBarry Smith   with `SNESCreate()`.
35189b94acceSBarry Smith 
3519c3339decSBarry Smith   Collective
3520c7afd0dbSLois Curfman McInnes 
35219b94acceSBarry Smith   Input Parameter:
3522f6dfbefdSBarry Smith . snes - the `SNES` context
35239b94acceSBarry Smith 
352436851e7fSLois Curfman McInnes   Level: beginner
352536851e7fSLois Curfman McInnes 
35261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
35279b94acceSBarry Smith @*/
3528d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3529d71ae5a4SJacob Faibussowitsch {
35303a40ed3dSBarry Smith   PetscFunctionBegin;
35313ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3532f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3533f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
35349371c9d4SSatish Balay     *snes = NULL;
35353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
35369371c9d4SSatish Balay   }
3537d4bb536fSBarry Smith 
3538f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
35399566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
35406b8b9a38SLisandro Dalcin 
3541e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
35429566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3543f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
35446d4c513bSLisandro Dalcin 
35459566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
35469566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
35479566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
35489566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35496b8b9a38SLisandro Dalcin 
35509566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
355148a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
355248a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3553f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3554f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35559566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35579b94acceSBarry Smith }
35589b94acceSBarry Smith 
35599b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35609b94acceSBarry Smith 
3561a8054027SBarry Smith /*@
35620b4b7b1cSBarry Smith   SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`.
3563a8054027SBarry Smith 
3564c3339decSBarry Smith   Logically Collective
3565a8054027SBarry Smith 
3566a8054027SBarry Smith   Input Parameters:
3567f6dfbefdSBarry Smith + snes - the `SNES` context
3568d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35693b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3570a8054027SBarry Smith 
3571a8054027SBarry Smith   Options Database Keys:
3572420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35733d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3574420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35753d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3576a8054027SBarry Smith 
3577dc4c0fb0SBarry Smith   Level: intermediate
3578dc4c0fb0SBarry Smith 
3579420bcc1bSBarry Smith   Notes:
3580a8054027SBarry Smith   The default is 1
3581420bcc1bSBarry Smith 
3582f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3583d8e291bfSBarry Smith 
3584f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3585a8054027SBarry Smith 
35863201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3587f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3588a8054027SBarry Smith @*/
3589d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3590d71ae5a4SJacob Faibussowitsch {
3591a8054027SBarry Smith   PetscFunctionBegin;
35920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35935f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35945f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3595c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3596a8054027SBarry Smith   snes->lagpreconditioner = lag;
35973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3598a8054027SBarry Smith }
3599a8054027SBarry Smith 
3600efd51863SBarry Smith /*@
3601f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3602efd51863SBarry Smith 
3603c3339decSBarry Smith   Logically Collective
3604efd51863SBarry Smith 
3605efd51863SBarry Smith   Input Parameters:
3606f6dfbefdSBarry Smith + snes  - the `SNES` context
3607efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3608efd51863SBarry Smith 
3609f6dfbefdSBarry Smith   Options Database Key:
361067b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3611efd51863SBarry Smith 
3612efd51863SBarry Smith   Level: intermediate
3613efd51863SBarry Smith 
36140b4b7b1cSBarry Smith   Notes:
36150b4b7b1cSBarry Smith   Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement.
36160b4b7b1cSBarry Smith 
3617f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3618c0df2a02SJed Brown 
36193201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
362054c05997SPierre Jolivet           `SNESSetDM()`, `SNESSolve()`
3621efd51863SBarry Smith @*/
3622d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3623d71ae5a4SJacob Faibussowitsch {
3624efd51863SBarry Smith   PetscFunctionBegin;
3625efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3626efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3627efd51863SBarry Smith   snes->gridsequence = steps;
36283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3629efd51863SBarry Smith }
3630efd51863SBarry Smith 
3631fa19ca70SBarry Smith /*@
3632f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3633fa19ca70SBarry Smith 
3634c3339decSBarry Smith   Logically Collective
3635fa19ca70SBarry Smith 
3636fa19ca70SBarry Smith   Input Parameter:
3637f6dfbefdSBarry Smith . snes - the `SNES` context
3638fa19ca70SBarry Smith 
3639fa19ca70SBarry Smith   Output Parameter:
3640fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3641fa19ca70SBarry Smith 
3642fa19ca70SBarry Smith   Level: intermediate
3643fa19ca70SBarry Smith 
36443201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3645fa19ca70SBarry Smith @*/
3646d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3647d71ae5a4SJacob Faibussowitsch {
3648fa19ca70SBarry Smith   PetscFunctionBegin;
3649fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3650fa19ca70SBarry Smith   *steps = snes->gridsequence;
36513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3652fa19ca70SBarry Smith }
3653fa19ca70SBarry Smith 
3654a8054027SBarry Smith /*@
3655f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3656a8054027SBarry Smith 
36573f9fe445SBarry Smith   Not Collective
3658a8054027SBarry Smith 
3659a8054027SBarry Smith   Input Parameter:
3660f6dfbefdSBarry Smith . snes - the `SNES` context
3661a8054027SBarry Smith 
3662a8054027SBarry Smith   Output Parameter:
3663a8054027SBarry 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
36643b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3665a8054027SBarry Smith 
3666dc4c0fb0SBarry Smith   Level: intermediate
3667dc4c0fb0SBarry Smith 
3668a8054027SBarry Smith   Notes:
3669a8054027SBarry Smith   The default is 1
3670f6dfbefdSBarry Smith 
3671a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3672a8054027SBarry Smith 
36733201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3674a8054027SBarry Smith @*/
3675d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3676d71ae5a4SJacob Faibussowitsch {
3677a8054027SBarry Smith   PetscFunctionBegin;
36780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3679a8054027SBarry Smith   *lag = snes->lagpreconditioner;
36803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3681a8054027SBarry Smith }
3682a8054027SBarry Smith 
3683e35cf81dSBarry Smith /*@
3684f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3685e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3686e35cf81dSBarry Smith 
3687c3339decSBarry Smith   Logically Collective
3688e35cf81dSBarry Smith 
3689e35cf81dSBarry Smith   Input Parameters:
3690f6dfbefdSBarry Smith + snes - the `SNES` context
3691e35cf81dSBarry 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
3692fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3693e35cf81dSBarry Smith 
3694e35cf81dSBarry Smith   Options Database Keys:
369579a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36963d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
369779a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36983d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3699e35cf81dSBarry Smith 
3700dc4c0fb0SBarry Smith   Level: intermediate
3701dc4c0fb0SBarry Smith 
3702e35cf81dSBarry Smith   Notes:
3703e35cf81dSBarry Smith   The default is 1
3704f6dfbefdSBarry Smith 
3705e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3706f6dfbefdSBarry Smith 
3707fe3ffe1eSBarry 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
3708fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3709e35cf81dSBarry Smith 
37103201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3711e35cf81dSBarry Smith @*/
3712d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3713d71ae5a4SJacob Faibussowitsch {
3714e35cf81dSBarry Smith   PetscFunctionBegin;
37150700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
37165f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
37175f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3718c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3719e35cf81dSBarry Smith   snes->lagjacobian = lag;
37203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3721e35cf81dSBarry Smith }
3722e35cf81dSBarry Smith 
3723e35cf81dSBarry Smith /*@
3724f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3725e35cf81dSBarry Smith 
37263f9fe445SBarry Smith   Not Collective
3727e35cf81dSBarry Smith 
3728e35cf81dSBarry Smith   Input Parameter:
3729f6dfbefdSBarry Smith . snes - the `SNES` context
3730e35cf81dSBarry Smith 
3731e35cf81dSBarry Smith   Output Parameter:
3732e35cf81dSBarry 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
3733e35cf81dSBarry Smith          the Jacobian is built etc.
3734e35cf81dSBarry Smith 
3735dc4c0fb0SBarry Smith   Level: intermediate
3736dc4c0fb0SBarry Smith 
3737e35cf81dSBarry Smith   Notes:
3738e35cf81dSBarry Smith   The default is 1
3739f6dfbefdSBarry Smith 
3740f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3741e35cf81dSBarry Smith 
37423201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3743e35cf81dSBarry Smith 
3744e35cf81dSBarry Smith @*/
3745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3746d71ae5a4SJacob Faibussowitsch {
3747e35cf81dSBarry Smith   PetscFunctionBegin;
37480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3749e35cf81dSBarry Smith   *lag = snes->lagjacobian;
37503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3751e35cf81dSBarry Smith }
3752e35cf81dSBarry Smith 
375337ec4e1aSPeter Brune /*@
3754f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
375537ec4e1aSPeter Brune 
3756c3339decSBarry Smith   Logically collective
375737ec4e1aSPeter Brune 
3758d8d19677SJose E. Roman   Input Parameters:
3759f6dfbefdSBarry Smith + snes - the `SNES` context
37609d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
376137ec4e1aSPeter Brune 
376237ec4e1aSPeter Brune   Options Database Keys:
376379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37643d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
376579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37663d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37673d5a8a6aSBarry Smith 
3768dc4c0fb0SBarry Smith   Level: advanced
3769dc4c0fb0SBarry Smith 
377095452b02SPatrick Sanan   Notes:
3771420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3772f6dfbefdSBarry Smith 
377395452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
377437ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
377537ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
377637ec4e1aSPeter Brune 
377742747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
377837ec4e1aSPeter Brune @*/
3779d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3780d71ae5a4SJacob Faibussowitsch {
378137ec4e1aSPeter Brune   PetscFunctionBegin;
378237ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
378337ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
378437ec4e1aSPeter Brune   snes->lagjac_persist = flg;
37853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
378637ec4e1aSPeter Brune }
378737ec4e1aSPeter Brune 
378837ec4e1aSPeter Brune /*@
3789d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
379037ec4e1aSPeter Brune 
3791c3339decSBarry Smith   Logically Collective
379237ec4e1aSPeter Brune 
3793d8d19677SJose E. Roman   Input Parameters:
3794f6dfbefdSBarry Smith + snes - the `SNES` context
37959d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
379637ec4e1aSPeter Brune 
379737ec4e1aSPeter Brune   Options Database Keys:
379879a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37993d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
380079a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
38013d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
380237ec4e1aSPeter Brune 
3803dc4c0fb0SBarry Smith   Level: developer
3804dc4c0fb0SBarry Smith 
380595452b02SPatrick Sanan   Notes:
3806420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3807f6dfbefdSBarry Smith 
380895452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
380937ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
381037ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
381137ec4e1aSPeter Brune 
38121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
381337ec4e1aSPeter Brune @*/
3814d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3815d71ae5a4SJacob Faibussowitsch {
381637ec4e1aSPeter Brune   PetscFunctionBegin;
381737ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
381837ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
381937ec4e1aSPeter Brune   snes->lagpre_persist = flg;
38203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
382137ec4e1aSPeter Brune }
382237ec4e1aSPeter Brune 
38239b94acceSBarry Smith /*@
3824f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3825be5caee7SBarry Smith 
3826c3339decSBarry Smith   Logically Collective
3827be5caee7SBarry Smith 
3828be5caee7SBarry Smith   Input Parameters:
3829f6dfbefdSBarry Smith + snes  - the `SNES` context
3830f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3831be5caee7SBarry Smith 
3832f6dfbefdSBarry Smith   Options Database Key:
3833be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3834be5caee7SBarry Smith 
3835dc4c0fb0SBarry Smith   Level: intermediate
3836dc4c0fb0SBarry Smith 
3837f6dfbefdSBarry Smith   Note:
3838f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3839be5caee7SBarry Smith 
38403201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3841be5caee7SBarry Smith @*/
3842d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3843d71ae5a4SJacob Faibussowitsch {
3844be5caee7SBarry Smith   PetscFunctionBegin;
3845be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3846be5caee7SBarry Smith   snes->forceiteration = force;
38473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3848be5caee7SBarry Smith }
3849be5caee7SBarry Smith 
385085216dc7SFande Kong /*@
3851f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
385285216dc7SFande Kong 
3853c3339decSBarry Smith   Logically Collective
385485216dc7SFande Kong 
38552fe279fdSBarry Smith   Input Parameter:
3856f6dfbefdSBarry Smith . snes - the `SNES` context
385785216dc7SFande Kong 
385885216dc7SFande Kong   Output Parameter:
3859dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
386085216dc7SFande Kong 
386106dd6b0eSSatish Balay   Level: intermediate
386206dd6b0eSSatish Balay 
38633201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
386485216dc7SFande Kong @*/
3865d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3866d71ae5a4SJacob Faibussowitsch {
386785216dc7SFande Kong   PetscFunctionBegin;
386885216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
386985216dc7SFande Kong   *force = snes->forceiteration;
38703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
387185216dc7SFande Kong }
3872be5caee7SBarry Smith 
3873be5caee7SBarry Smith /*@
38740b4b7b1cSBarry Smith   SNESSetTolerances - Sets various parameters used in `SNES` convergence tests.
38759b94acceSBarry Smith 
3876c3339decSBarry Smith   Logically Collective
3877c7afd0dbSLois Curfman McInnes 
38789b94acceSBarry Smith   Input Parameters:
3879f6dfbefdSBarry Smith + snes   - the `SNES` context
38800b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $
38810b4b7b1cSBarry Smith . rtol   - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $
38825358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
38830b4b7b1cSBarry Smith . maxit  - the maximum number of iterations allowed in the solver, default 50.
38840b4b7b1cSBarry Smith - maxf   - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3885fee21e36SBarry Smith 
388633174efeSLois Curfman McInnes   Options Database Keys:
388777e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
388877e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
388977e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
389077e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
389177e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
38929b94acceSBarry Smith 
389336851e7fSLois Curfman McInnes   Level: intermediate
389436851e7fSLois Curfman McInnes 
389577e5a1f9SBarry Smith   Note:
389677e5a1f9SBarry Smith   All parameters must be non-negative
389777e5a1f9SBarry Smith 
389877e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
389977e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
390077e5a1f9SBarry Smith 
390177e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
390277e5a1f9SBarry Smith 
390377e5a1f9SBarry Smith   Fortran Note:
390477e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
390577e5a1f9SBarry Smith 
39063201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
39079b94acceSBarry Smith @*/
3908d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3909d71ae5a4SJacob Faibussowitsch {
39103a40ed3dSBarry Smith   PetscFunctionBegin;
39110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3912c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3913c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3914c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3915c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3916c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3917c5eb9154SBarry Smith 
391877e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
391977e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
392077e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
39215f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3922ab54825eSJed Brown     snes->abstol = abstol;
3923ab54825eSJed Brown   }
392477e5a1f9SBarry Smith 
392577e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
392677e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
392777e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
39285f80ce2aSJacob 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);
3929ab54825eSJed Brown     snes->rtol = rtol;
3930ab54825eSJed Brown   }
393177e5a1f9SBarry Smith 
393277e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
393377e5a1f9SBarry Smith     snes->stol = snes->default_stol;
393477e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
39355f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3936c60f73f4SPeter Brune     snes->stol = stol;
3937ab54825eSJed Brown   }
393877e5a1f9SBarry Smith 
3939835f2295SStefano Zampini   if (maxit == PETSC_DETERMINE) {
394077e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
3941835f2295SStefano Zampini   } else if (maxit == PETSC_UNLIMITED) {
394277e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
394377e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
394463a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3945ab54825eSJed Brown     snes->max_its = maxit;
3946ab54825eSJed Brown   }
394777e5a1f9SBarry Smith 
3948835f2295SStefano Zampini   if (maxf == PETSC_DETERMINE) {
394977e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
3950835f2295SStefano Zampini   } else if (maxf == PETSC_UNLIMITED || maxf == -1) {
395177e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
395277e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
395377e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3954ab54825eSJed Brown     snes->max_funcs = maxf;
3955ab54825eSJed Brown   }
39563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39579b94acceSBarry Smith }
39589b94acceSBarry Smith 
3959e4d06f11SPatrick Farrell /*@
3960f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3961e4d06f11SPatrick Farrell 
3962c3339decSBarry Smith   Logically Collective
3963e4d06f11SPatrick Farrell 
3964e4d06f11SPatrick Farrell   Input Parameters:
3965f6dfbefdSBarry Smith + snes   - the `SNES` context
39660b4b7b1cSBarry 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
39670b4b7b1cSBarry Smith            is stopped due to divergence.
3968e4d06f11SPatrick Farrell 
3969f6dfbefdSBarry Smith   Options Database Key:
3970dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3971e4d06f11SPatrick Farrell 
3972e4d06f11SPatrick Farrell   Level: intermediate
3973e4d06f11SPatrick Farrell 
397477e5a1f9SBarry Smith   Notes:
397577e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
3976e5cd489fSStefano Zampini 
397777e5a1f9SBarry Smith   Fortran Note:
397877e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
397977e5a1f9SBarry Smith 
398077e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
3981e4d06f11SPatrick Farrell @*/
3982d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3983d71ae5a4SJacob Faibussowitsch {
3984e4d06f11SPatrick Farrell   PetscFunctionBegin;
3985e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3986e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
398777e5a1f9SBarry Smith 
398877e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
398977e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
399077e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
399177e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
399277e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
399377e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
399477e5a1f9SBarry Smith     snes->divtol = divtol;
399577e5a1f9SBarry Smith   }
39963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3997e4d06f11SPatrick Farrell }
3998e4d06f11SPatrick Farrell 
39999b94acceSBarry Smith /*@
40000b4b7b1cSBarry Smith   SNESGetTolerances - Gets various parameters used in `SNES` convergence tests.
400133174efeSLois Curfman McInnes 
4002c7afd0dbSLois Curfman McInnes   Not Collective
4003c7afd0dbSLois Curfman McInnes 
400477e5a1f9SBarry Smith   Input Parameter:
400577e5a1f9SBarry Smith . snes - the `SNES` context
400677e5a1f9SBarry Smith 
400777e5a1f9SBarry Smith   Output Parameters:
40080b4b7b1cSBarry Smith + atol  - the absolute convergence tolerance
40090b4b7b1cSBarry Smith . rtol  - the relative convergence tolerance
401077e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
40110b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed
40120b4b7b1cSBarry Smith - maxf  - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound
4013fee21e36SBarry Smith 
401436851e7fSLois Curfman McInnes   Level: intermediate
401536851e7fSLois Curfman McInnes 
40160b4b7b1cSBarry Smith   Notes:
40170b4b7b1cSBarry Smith   See `SNESSetTolerances()` for details on the parameters.
40180b4b7b1cSBarry Smith 
4019dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
4020dc4c0fb0SBarry Smith 
40211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
402233174efeSLois Curfman McInnes @*/
4023d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
4024d71ae5a4SJacob Faibussowitsch {
40253a40ed3dSBarry Smith   PetscFunctionBegin;
40260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
402785385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
402833174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
4029c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
403033174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
403133174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
40323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
403333174efeSLois Curfman McInnes }
403433174efeSLois Curfman McInnes 
4035e4d06f11SPatrick Farrell /*@
4036e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4037e4d06f11SPatrick Farrell 
4038e4d06f11SPatrick Farrell   Not Collective
4039e4d06f11SPatrick Farrell 
4040e4d06f11SPatrick Farrell   Input Parameters:
4041f6dfbefdSBarry Smith + snes   - the `SNES` context
4042e4d06f11SPatrick Farrell - divtol - divergence tolerance
4043e4d06f11SPatrick Farrell 
4044e4d06f11SPatrick Farrell   Level: intermediate
4045e4d06f11SPatrick Farrell 
40461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4047e4d06f11SPatrick Farrell @*/
4048d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4049d71ae5a4SJacob Faibussowitsch {
4050e4d06f11SPatrick Farrell   PetscFunctionBegin;
4051e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4052e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
40533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4054e4d06f11SPatrick Farrell }
4055e4d06f11SPatrick Farrell 
40566ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40576ba87a44SLisandro Dalcin 
4058d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4059d71ae5a4SJacob Faibussowitsch {
4060b271bb04SBarry Smith   PetscDrawLG      lg;
4061b271bb04SBarry Smith   PetscReal        x, y, per;
4062b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4063b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4064b271bb04SBarry Smith   PetscDraw        draw;
4065b271bb04SBarry Smith 
4066459f5d12SBarry Smith   PetscFunctionBegin;
40674d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40689566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40699566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40709566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40719566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4072b271bb04SBarry Smith   x = (PetscReal)n;
407377b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
407494c9c6d3SKarl Rupp   else y = -15.0;
40759566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40766934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40779566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40789566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4079b271bb04SBarry Smith   }
4080b271bb04SBarry Smith 
40819566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
40829566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40839566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4084aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
40859566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4086b271bb04SBarry Smith   x = (PetscReal)n;
4087b271bb04SBarry Smith   y = 100.0 * per;
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, 2, &lg));
40959371c9d4SSatish Balay   if (!n) {
40969371c9d4SSatish Balay     prev = rnorm;
40979371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
40989371c9d4SSatish Balay   }
40999566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41009566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4101b271bb04SBarry Smith   x = (PetscReal)n;
4102b271bb04SBarry Smith   y = (prev - rnorm) / prev;
41039566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
41046934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41059566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41069566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4107b271bb04SBarry Smith   }
4108b271bb04SBarry Smith 
41099566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
41109566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
41119566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
41129566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4113b271bb04SBarry Smith   x = (PetscReal)n;
4114b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4115b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
41169566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4117b271bb04SBarry Smith   }
41186934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41199566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41209566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4121b271bb04SBarry Smith   }
4122b271bb04SBarry Smith   prev = rnorm;
41233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4124b271bb04SBarry Smith }
4125b271bb04SBarry Smith 
4126228d79bcSJed Brown /*@
41272d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41282d157150SStefano Zampini 
41292d157150SStefano Zampini   Collective
41302d157150SStefano Zampini 
41312d157150SStefano Zampini   Input Parameters:
41322d157150SStefano Zampini + snes  - the `SNES` context
41332d157150SStefano Zampini . it    - current iteration
41342d157150SStefano Zampini . xnorm - 2-norm of current iterate
41352d157150SStefano Zampini . snorm - 2-norm of current step
41362d157150SStefano Zampini - fnorm - 2-norm of function
41372d157150SStefano Zampini 
41382d157150SStefano Zampini   Level: developer
41392d157150SStefano Zampini 
41402d157150SStefano Zampini   Note:
4141420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41422d157150SStefano Zampini   It does not typically need to be called by the user.
41432d157150SStefano Zampini 
4144c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
41452d157150SStefano Zampini @*/
41462d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41472d157150SStefano Zampini {
41482d157150SStefano Zampini   PetscFunctionBegin;
41492d157150SStefano Zampini   if (!snes->reason) {
41502d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41512d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41522d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41532d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41542d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41552d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41562d157150SStefano Zampini     }
41572d157150SStefano Zampini   }
41582d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41592d157150SStefano Zampini }
41602d157150SStefano Zampini 
41612d157150SStefano Zampini /*@
41620b4b7b1cSBarry Smith   SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database
4163228d79bcSJed Brown 
4164c3339decSBarry Smith   Collective
4165228d79bcSJed Brown 
4166228d79bcSJed Brown   Input Parameters:
4167f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
41680b4b7b1cSBarry Smith . iter  - current iteration number
41690b4b7b1cSBarry Smith - rnorm - current relative norm of the residual
4170228d79bcSJed Brown 
4171dc4c0fb0SBarry Smith   Level: developer
4172dc4c0fb0SBarry Smith 
4173f6dfbefdSBarry Smith   Note:
4174420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4175228d79bcSJed Brown   It does not typically need to be called by the user.
4176228d79bcSJed Brown 
41771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4178228d79bcSJed Brown @*/
4179d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4180d71ae5a4SJacob Faibussowitsch {
41817a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
41827a03ce2fSLisandro Dalcin 
41837a03ce2fSLisandro Dalcin   PetscFunctionBegin;
41845f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
41859566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
418648a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
41879566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
41883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41897a03ce2fSLisandro Dalcin }
41907a03ce2fSLisandro Dalcin 
41919b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
41929b94acceSBarry Smith 
4193bf388a1fSBarry Smith /*MC
4194f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4195bf388a1fSBarry Smith 
4196bf388a1fSBarry Smith      Synopsis:
4197aaa7dc30SBarry Smith      #include <petscsnes.h>
419837fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4199bf388a1fSBarry Smith 
4200c3339decSBarry Smith      Collective
42011843f636SBarry Smith 
42021843f636SBarry Smith     Input Parameters:
4203f6dfbefdSBarry Smith +    snes - the `SNES` context
4204bf388a1fSBarry Smith .    its - iteration number
4205bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4206bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4207bf388a1fSBarry Smith 
4208878cb397SSatish Balay    Level: advanced
4209878cb397SSatish Balay 
42101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4211bf388a1fSBarry Smith M*/
4212bf388a1fSBarry Smith 
42139b94acceSBarry Smith /*@C
4214a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
42150b4b7b1cSBarry Smith   iteration of the `SNES` nonlinear solver to display the iteration's
42169b94acceSBarry Smith   progress.
42179b94acceSBarry Smith 
4218c3339decSBarry Smith   Logically Collective
4219fee21e36SBarry Smith 
4220c7afd0dbSLois Curfman McInnes   Input Parameters:
4221f6dfbefdSBarry Smith + snes           - the `SNES` context
422220f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4223420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
422449abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
42259b94acceSBarry Smith 
42269665c990SLois Curfman McInnes   Options Database Keys:
4227f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4228798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4229dc4c0fb0SBarry 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
4230c7afd0dbSLois Curfman McInnes                                 the options database.
42319665c990SLois Curfman McInnes 
4232dc4c0fb0SBarry Smith   Level: intermediate
4233dc4c0fb0SBarry Smith 
4234f6dfbefdSBarry Smith   Note:
42356bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4236f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42376bc08f3fSLois Curfman McInnes   order in which they were set.
4238639f9d9dSBarry Smith 
4239420bcc1bSBarry Smith   Fortran Note:
4240f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4241025f1a04SBarry Smith 
424249abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
42439b94acceSBarry Smith @*/
424449abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
4245d71ae5a4SJacob Faibussowitsch {
4246b90d0a6eSBarry Smith   PetscInt  i;
424778064530SBarry Smith   PetscBool identical;
4248b90d0a6eSBarry Smith 
42493a40ed3dSBarry Smith   PetscFunctionBegin;
42500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4251b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
42529566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42533ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4254649052a6SBarry Smith   }
42555f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42566e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4257b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4258835f2295SStefano Zampini   snes->monitorcontext[snes->numbermonitors++] = mctx;
42593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42609b94acceSBarry Smith }
42619b94acceSBarry Smith 
4262a278d85bSSatish Balay /*@
4263f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42645cd90555SBarry Smith 
4265c3339decSBarry Smith   Logically Collective
4266c7afd0dbSLois Curfman McInnes 
42672fe279fdSBarry Smith   Input Parameter:
4268f6dfbefdSBarry Smith . snes - the `SNES` context
42695cd90555SBarry Smith 
42701a480d89SAdministrator   Options Database Key:
4271a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4272dc4c0fb0SBarry Smith                          into a code by calls to `SNESMonitorSet()`, but does not cancel those
4273c7afd0dbSLois Curfman McInnes                          set via the options database
42745cd90555SBarry Smith 
4275dc4c0fb0SBarry Smith   Level: intermediate
4276dc4c0fb0SBarry Smith 
4277f6dfbefdSBarry Smith   Note:
4278f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
42795cd90555SBarry Smith 
42801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
42815cd90555SBarry Smith @*/
4282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4283d71ae5a4SJacob Faibussowitsch {
4284d952e501SBarry Smith   PetscInt i;
4285d952e501SBarry Smith 
42865cd90555SBarry Smith   PetscFunctionBegin;
42870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4288d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
428948a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4290d952e501SBarry Smith   }
42915cd90555SBarry Smith   snes->numbermonitors = 0;
42923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42935cd90555SBarry Smith }
42945cd90555SBarry Smith 
4295bf388a1fSBarry Smith /*MC
4296bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4297bf388a1fSBarry Smith 
4298bf388a1fSBarry Smith      Synopsis:
4299aaa7dc30SBarry Smith      #include <petscsnes.h>
430037fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4301bf388a1fSBarry Smith 
4302c3339decSBarry Smith      Collective
43031843f636SBarry Smith 
43041843f636SBarry Smith     Input Parameters:
4305f6dfbefdSBarry Smith +    snes - the `SNES` context
4306bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4307bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4308bf388a1fSBarry Smith .    gnorm - 2-norm of current step
43091843f636SBarry Smith .    f - 2-norm of function
43101843f636SBarry Smith -    cctx - [optional] convergence context
43111843f636SBarry Smith 
43121843f636SBarry Smith     Output Parameter:
43131843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4314bf388a1fSBarry Smith 
4315878cb397SSatish Balay    Level: intermediate
4316bf388a1fSBarry Smith 
4317c948abdaSPierre Jolivet .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`
4318bf388a1fSBarry Smith M*/
4319bf388a1fSBarry Smith 
43209b94acceSBarry Smith /*@C
43219b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
43229b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
43239b94acceSBarry Smith 
4324c3339decSBarry Smith   Logically Collective
4325fee21e36SBarry Smith 
4326c7afd0dbSLois Curfman McInnes   Input Parameters:
4327f6dfbefdSBarry Smith + snes                        - the `SNES` context
4328e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4329dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4330dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43319b94acceSBarry Smith 
433236851e7fSLois Curfman McInnes   Level: advanced
433336851e7fSLois Curfman McInnes 
43341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43359b94acceSBarry Smith @*/
4336d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4337d71ae5a4SJacob Faibussowitsch {
43383a40ed3dSBarry Smith   PetscFunctionBegin;
43390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4340e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
43411baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4342bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43437f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
434485385478SLisandro Dalcin   snes->cnvP                  = cctx;
43453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43469b94acceSBarry Smith }
43479b94acceSBarry Smith 
434852baeb72SSatish Balay /*@
43490b4b7b1cSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4350184914b5SBarry Smith 
4351184914b5SBarry Smith   Not Collective
4352184914b5SBarry Smith 
4353184914b5SBarry Smith   Input Parameter:
4354f6dfbefdSBarry Smith . snes - the `SNES` context
4355184914b5SBarry Smith 
4356184914b5SBarry Smith   Output Parameter:
4357f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4358184914b5SBarry Smith 
4359f6dfbefdSBarry Smith   Options Database Key:
43606a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43616a4d7782SBarry Smith 
4362184914b5SBarry Smith   Level: intermediate
4363184914b5SBarry Smith 
4364f6dfbefdSBarry Smith   Note:
4365f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4366184914b5SBarry Smith 
43671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4368184914b5SBarry Smith @*/
4369d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4370d71ae5a4SJacob Faibussowitsch {
4371184914b5SBarry Smith   PetscFunctionBegin;
43720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43734f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4374184914b5SBarry Smith   *reason = snes->reason;
43753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4376184914b5SBarry Smith }
4377184914b5SBarry Smith 
4378c4421ceaSFande Kong /*@C
4379f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4380c4421ceaSFande Kong 
4381c4421ceaSFande Kong   Not Collective
4382c4421ceaSFande Kong 
4383c4421ceaSFande Kong   Input Parameter:
4384f6dfbefdSBarry Smith . snes - the `SNES` context
4385c4421ceaSFande Kong 
4386c4421ceaSFande Kong   Output Parameter:
4387dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4388c4421ceaSFande Kong 
438999c90e12SSatish Balay   Level: beginner
4390c4421ceaSFande Kong 
43911cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4392c4421ceaSFande Kong @*/
4393d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4394d71ae5a4SJacob Faibussowitsch {
4395c4421ceaSFande Kong   PetscFunctionBegin;
4396c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43974f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4398c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
43993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4400c4421ceaSFande Kong }
4401c4421ceaSFande Kong 
440233866048SMatthew G. Knepley /*@
4403f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
440433866048SMatthew G. Knepley 
440533866048SMatthew G. Knepley   Not Collective
440633866048SMatthew G. Knepley 
440733866048SMatthew G. Knepley   Input Parameters:
4408f6dfbefdSBarry Smith + snes   - the `SNES` context
4409f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
441033866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
441133866048SMatthew G. Knepley 
4412f6dfbefdSBarry Smith   Level: developer
4413f6dfbefdSBarry Smith 
4414420bcc1bSBarry Smith   Developer Note:
4415f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
441633866048SMatthew G. Knepley 
44171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
441833866048SMatthew G. Knepley @*/
4419d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4420d71ae5a4SJacob Faibussowitsch {
442133866048SMatthew G. Knepley   PetscFunctionBegin;
442233866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44235f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
442433866048SMatthew G. Knepley   snes->reason = reason;
44253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
442633866048SMatthew G. Knepley }
442733866048SMatthew G. Knepley 
4428c9005455SLois Curfman McInnes /*@
4429420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4430c9005455SLois Curfman McInnes 
4431c3339decSBarry Smith   Logically Collective
4432fee21e36SBarry Smith 
4433c7afd0dbSLois Curfman McInnes   Input Parameters:
4434f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44358c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4436cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4437420bcc1bSBarry Smith . na    - size of `a` and `its`
4438f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4439758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4440c7afd0dbSLois Curfman McInnes 
4441dc4c0fb0SBarry Smith   Level: intermediate
4442dc4c0fb0SBarry Smith 
4443308dcc3eSBarry Smith   Notes:
4444ce78bad3SBarry 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
444577e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4446308dcc3eSBarry Smith 
4447c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4448c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4449c9005455SLois Curfman McInnes   during the section of code that is being timed.
4450c9005455SLois Curfman McInnes 
4451420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4452420bcc1bSBarry Smith 
44531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4454c9005455SLois Curfman McInnes @*/
4455d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4456d71ae5a4SJacob Faibussowitsch {
44573a40ed3dSBarry Smith   PetscFunctionBegin;
44580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44594f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44604f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44617a1ec6d4SBarry Smith   if (!a) {
446277e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44639566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4464071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4465308dcc3eSBarry Smith   }
4466c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4467758f92a0SBarry Smith   snes->conv_hist_its   = its;
4468115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4469a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4470758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4472758f92a0SBarry Smith }
4473758f92a0SBarry Smith 
4474d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4475c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4476c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
447799e0435eSBarry Smith 
4478d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4479d71ae5a4SJacob Faibussowitsch {
4480308dcc3eSBarry Smith   mxArray   *mat;
4481308dcc3eSBarry Smith   PetscInt   i;
4482308dcc3eSBarry Smith   PetscReal *ar;
4483308dcc3eSBarry Smith 
4484308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4485308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4486f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
448711cc89d2SBarry Smith   return mat;
4488308dcc3eSBarry Smith }
4489308dcc3eSBarry Smith #endif
4490308dcc3eSBarry Smith 
44910c4c9dddSBarry Smith /*@C
4492420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4493758f92a0SBarry Smith 
44943f9fe445SBarry Smith   Not Collective
4495758f92a0SBarry Smith 
4496758f92a0SBarry Smith   Input Parameter:
4497f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4498758f92a0SBarry Smith 
4499758f92a0SBarry Smith   Output Parameters:
4500f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4501758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4502758f92a0SBarry Smith          negative if not converged) for each solve.
450320f4b53cSBarry Smith - na  - size of `a` and `its`
4504758f92a0SBarry Smith 
4505dc4c0fb0SBarry Smith   Level: intermediate
4506dc4c0fb0SBarry Smith 
450720f4b53cSBarry Smith   Note:
450820f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
450920f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
451020f4b53cSBarry Smith   during the section of code that is being timed.
451120f4b53cSBarry Smith 
4512ce78bad3SBarry Smith   Fortran Notes:
4513ce78bad3SBarry Smith   Return the arrays with ``SNESRestoreConvergenceHistory()`
4514ce78bad3SBarry Smith 
4515ce78bad3SBarry Smith   Use the arguments
4516dc4c0fb0SBarry Smith .vb
4517ce78bad3SBarry Smith   PetscReal, pointer :: a(:)
4518ce78bad3SBarry Smith   PetscInt, pointer :: its(:)
4519dc4c0fb0SBarry Smith .ve
4520758f92a0SBarry Smith 
45211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4522758f92a0SBarry Smith @*/
4523d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4524d71ae5a4SJacob Faibussowitsch {
4525758f92a0SBarry Smith   PetscFunctionBegin;
45260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4527758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4528758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4529115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
45303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4531c9005455SLois Curfman McInnes }
4532c9005455SLois Curfman McInnes 
4533ac226902SBarry Smith /*@C
453476b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4535eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
453653e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
453753e5d35bSStefano Zampini   evaluation.
453876b2cf59SMatthew Knepley 
4539c3339decSBarry Smith   Logically Collective
454076b2cf59SMatthew Knepley 
454176b2cf59SMatthew Knepley   Input Parameters:
4542a2b725a8SWilliam Gropp + snes - The nonlinear solver context
454353e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
454476b2cf59SMatthew Knepley 
4545fe97e370SBarry Smith   Level: advanced
4546fe97e370SBarry Smith 
4547420bcc1bSBarry Smith   Notes:
4548f6dfbefdSBarry 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
4549f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
455053e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
455153e5d35bSStefano Zampini   right before the direction step is computed.
4552ce78bad3SBarry Smith 
455353e5d35bSStefano Zampini   Users are free to modify the current residual vector,
455453e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
455553e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
4556ce78bad3SBarry Smith   vectors. For example, if one is adjusting the model parameters at each Newton step their code may look like
4557ce78bad3SBarry Smith .vb
4558ce78bad3SBarry Smith   PetscErrorCode update(SNES snes, PetscInt iteration)
4559ce78bad3SBarry Smith   {
4560ce78bad3SBarry Smith     PetscFunctionBeginUser;
4561ce78bad3SBarry Smith     if (iteration > 0) {
4562ce78bad3SBarry Smith       // update the model parameters here
4563ce78bad3SBarry Smith       Vec x,f;
4564ce78bad3SBarry Smith       PetscCall(SNESGetSolution(snes,&x));
4565ce78bad3SBarry Smith       PetcCall(SNESGetFunction(snes,&f,NULL,NULL));
4566ce78bad3SBarry Smith       PetscCall(SNESComputeFunction(snes,x,f));
4567ce78bad3SBarry Smith     }
4568ce78bad3SBarry Smith     PetscFunctionReturn(PETSC_SUCCESS);
4569ce78bad3SBarry Smith   }
4570ce78bad3SBarry Smith .ve
457176b2cf59SMatthew Knepley 
4572aaa8cc7dSPierre 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.
45736b7fb656SBarry Smith 
4574e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
457553e5d35bSStefano Zampini          `SNESMonitorSet()`
457676b2cf59SMatthew Knepley @*/
457753e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4578d71ae5a4SJacob Faibussowitsch {
457976b2cf59SMatthew Knepley   PetscFunctionBegin;
45800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4581e7788613SBarry Smith   snes->ops->update = func;
45823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
458376b2cf59SMatthew Knepley }
458476b2cf59SMatthew Knepley 
4585ffeef943SBarry Smith /*@
4586f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
45872a359c20SBarry Smith 
4588c3339decSBarry Smith   Collective
45892a359c20SBarry Smith 
4590e4094ef1SJacob Faibussowitsch   Input Parameters:
4591f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
45922a359c20SBarry Smith - viewer - the viewer to display the reason
45932a359c20SBarry Smith 
45942a359c20SBarry Smith   Options Database Keys:
4595ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4596ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4597eafd5ff0SAlex Lindsay 
4598420bcc1bSBarry Smith   Level: beginner
4599420bcc1bSBarry Smith 
4600f6dfbefdSBarry Smith   Note:
4601f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4602f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
46032a359c20SBarry Smith 
46041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4605f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4606f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4607db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
46082a359c20SBarry Smith @*/
4609d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4610d71ae5a4SJacob Faibussowitsch {
461175cca76cSMatthew G. Knepley   PetscViewerFormat format;
46122a359c20SBarry Smith   PetscBool         isAscii;
46132a359c20SBarry Smith 
46142a359c20SBarry Smith   PetscFunctionBegin;
461519a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
46169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
46172a359c20SBarry Smith   if (isAscii) {
46189566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
461965bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
462075cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
462175cca76cSMatthew G. Knepley       DM       dm;
462275cca76cSMatthew G. Knepley       Vec      u;
462375cca76cSMatthew G. Knepley       PetscDS  prob;
462475cca76cSMatthew G. Knepley       PetscInt Nf, f;
462595cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
462695cbbfd3SMatthew G. Knepley       void    **exactCtx;
462775cca76cSMatthew G. Knepley       PetscReal error;
462875cca76cSMatthew G. Knepley 
46299566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
46309566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
46319566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
46329566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
46339566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
46349566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
46359566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
46369566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
46379566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
463863a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
463975cca76cSMatthew G. Knepley     }
4640eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
46412a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
464263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46432a359c20SBarry Smith       } else {
464463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46452a359c20SBarry Smith       }
4646eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
46472a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
464863a3b9bcSJacob 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));
46492a359c20SBarry Smith       } else {
465063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46512a359c20SBarry Smith       }
46522a359c20SBarry Smith     }
465365bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46542a359c20SBarry Smith   }
46553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46562a359c20SBarry Smith }
46572a359c20SBarry Smith 
4658c4421ceaSFande Kong /*@C
4659c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4660aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4661c4421ceaSFande Kong 
4662c3339decSBarry Smith   Logically Collective
4663c4421ceaSFande Kong 
4664c4421ceaSFande Kong   Input Parameters:
4665f6dfbefdSBarry Smith + snes              - the `SNES` context
4666420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4667420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
466849abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4669420bcc1bSBarry Smith 
4670420bcc1bSBarry Smith   Calling sequence of `f`:
4671420bcc1bSBarry Smith + snes - the `SNES` context
467249abdd8aSBarry Smith - vctx - [optional] context for private data for the function
4673c4421ceaSFande Kong 
4674c4421ceaSFande Kong   Options Database Keys:
4675f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4676420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4677420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4678c4421ceaSFande Kong 
4679dc4c0fb0SBarry Smith   Level: intermediate
4680dc4c0fb0SBarry Smith 
4681f6dfbefdSBarry Smith   Note:
4682c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4683f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4684c4421ceaSFande Kong   order in which they were set.
4685c4421ceaSFande Kong 
468649abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
468749abdd8aSBarry Smith           `PetscCtxDestroyFn`
4688c4421ceaSFande Kong @*/
468949abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4690d71ae5a4SJacob Faibussowitsch {
4691c4421ceaSFande Kong   PetscInt  i;
4692c4421ceaSFande Kong   PetscBool identical;
4693c4421ceaSFande Kong 
4694c4421ceaSFande Kong   PetscFunctionBegin;
4695c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4696c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
46979566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
46983ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4699c4421ceaSFande Kong   }
47005f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4701c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4702c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4703835f2295SStefano Zampini   snes->reasonviewcontext[snes->numberreasonviews++] = vctx;
47043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4705c4421ceaSFande Kong }
4706c4421ceaSFande Kong 
470791f3e32bSBarry Smith /*@
4708420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
47090b4b7b1cSBarry Smith   All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
47102a359c20SBarry Smith 
4711c3339decSBarry Smith   Collective
47122a359c20SBarry Smith 
47132fe279fdSBarry Smith   Input Parameter:
4714f6dfbefdSBarry Smith . snes - the `SNES` object
47152a359c20SBarry Smith 
4716f6dfbefdSBarry Smith   Level: advanced
47172a359c20SBarry Smith 
47181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4719f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
47202a359c20SBarry Smith @*/
4721d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4722d71ae5a4SJacob Faibussowitsch {
47232a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
47242a359c20SBarry Smith 
47252a359c20SBarry Smith   PetscFunctionBegin;
47263ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
47272a359c20SBarry Smith   incall = PETSC_TRUE;
4728c4421ceaSFande Kong 
4729c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
473036d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4731c4421ceaSFande Kong 
4732c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
473336d43d94SBarry Smith   if (snes->convergedreasonviewer) {
473436d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
473536d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
473636d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
47372a359c20SBarry Smith   }
47382a359c20SBarry Smith   incall = PETSC_FALSE;
47393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47402a359c20SBarry Smith }
47412a359c20SBarry Smith 
4742487a658cSBarry Smith /*@
47430b4b7b1cSBarry Smith   SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
47449b94acceSBarry Smith 
4745c3339decSBarry Smith   Collective
4746c7afd0dbSLois Curfman McInnes 
4747b2002411SLois Curfman McInnes   Input Parameters:
4748f6dfbefdSBarry Smith + snes - the `SNES` context
47490b4b7b1cSBarry Smith . b    - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
475085385478SLisandro Dalcin - x    - the solution vector.
47519b94acceSBarry Smith 
4752dc4c0fb0SBarry Smith   Level: beginner
4753dc4c0fb0SBarry Smith 
4754f6dfbefdSBarry Smith   Note:
4755420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4756a9b45538SStefano Zampini   for the nonlinear solve prior to calling `SNESSolve()` .
47578ddd3da0SLois Curfman McInnes 
47581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4759db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4760a9b45538SStefano Zampini           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
47619b94acceSBarry Smith @*/
4762d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4763d71ae5a4SJacob Faibussowitsch {
4764ace3abfcSBarry Smith   PetscBool flg;
4765efd51863SBarry Smith   PetscInt  grid;
47660298fd71SBarry Smith   Vec       xcreated = NULL;
4767caa4e7f2SJed Brown   DM        dm;
4768052efed2SBarry Smith 
47693a40ed3dSBarry Smith   PetscFunctionBegin;
47700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4771a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4772a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47730700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
477485385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
477585385478SLisandro Dalcin 
477634b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
477706fc46c8SMatthew G. Knepley   {
477806fc46c8SMatthew G. Knepley     PetscViewer       viewer;
477906fc46c8SMatthew G. Knepley     PetscViewerFormat format;
47807c88af5aSMatthew G. Knepley     PetscInt          num;
478106fc46c8SMatthew G. Knepley     PetscBool         flg;
478206fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
478306fc46c8SMatthew G. Knepley 
478406fc46c8SMatthew G. Knepley     if (!incall) {
478534b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4786648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
478706fc46c8SMatthew G. Knepley       if (flg) {
478806fc46c8SMatthew G. Knepley         PetscConvEst conv;
478946079b62SMatthew G. Knepley         DM           dm;
479046079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
479146079b62SMatthew G. Knepley         PetscInt     Nf;
479206fc46c8SMatthew G. Knepley 
479306fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
47949566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
47959566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
47969566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
47979566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
47989566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
47999566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
48009566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
48019566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
48029566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
48039566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
48049566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4805648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
48069566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
48079566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
480806fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
480906fc46c8SMatthew G. Knepley       }
481034b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4811b2588ea6SMatthew G. Knepley       num = 1;
48129566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
481334b4d3a8SMatthew G. Knepley       if (flg) {
481434b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
481534b4d3a8SMatthew G. Knepley 
481634b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
48179566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
48189566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48199566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48209566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48219566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
48229566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
48239566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
482434b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
482534b4d3a8SMatthew G. Knepley       }
48267c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
48277c88af5aSMatthew G. Knepley       num = 0;
48289566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
48297c88af5aSMatthew G. Knepley       if (num) {
48307c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4831e03fd340SMatthew G. Knepley         const char *prefix;
48327c88af5aSMatthew G. Knepley 
48337c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
48349566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4835e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4836e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
48379566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48389566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48399566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48409566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4841e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48429566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48439566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
48447c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
48457c88af5aSMatthew G. Knepley       }
484606fc46c8SMatthew G. Knepley     }
484706fc46c8SMatthew G. Knepley   }
4848ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4849caa4e7f2SJed Brown   if (!x) {
48509566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48519566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4852a69afd8bSBarry Smith     x = xcreated;
4853a69afd8bSBarry Smith   }
48549566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4855f05ece33SBarry Smith 
48569566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4857efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
485885385478SLisandro Dalcin     /* set solution vector */
48599566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48609566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
486185385478SLisandro Dalcin     snes->vec_sol = x;
48629566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4863caa4e7f2SJed Brown 
4864caa4e7f2SJed Brown     /* set affine vector if provided */
48659566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48669566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
486785385478SLisandro Dalcin     snes->vec_rhs = b;
486885385478SLisandro Dalcin 
48695f80ce2aSJacob 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");
48705f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4871dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4872aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48739566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48749566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48753f149594SLisandro Dalcin 
48767eee914bSBarry Smith     if (!grid) {
48779927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4878dd568438SSatish Balay     }
4879d25893d9SBarry Smith 
4880abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
488112b1dd1aSStefano Zampini     PetscCall(SNESResetCounters(snes));
48822d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
48839566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4884dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
48859566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
48862d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4887422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
48883f149594SLisandro Dalcin 
488937ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
489037ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
489137ec4e1aSPeter Brune 
4892648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
48939566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4894c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
48959566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
48965968eb51SBarry Smith 
48975f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
48989c8e83a9SBarry Smith     if (snes->reason < 0) break;
4899efd51863SBarry Smith     if (grid < snes->gridsequence) {
4900efd51863SBarry Smith       DM  fine;
4901efd51863SBarry Smith       Vec xnew;
4902efd51863SBarry Smith       Mat interp;
4903efd51863SBarry Smith 
49049566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
49055f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
49062eace19aSMatthew G. Knepley       PetscCall(DMGetCoordinatesLocalSetUp(fine));
49079566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
49089566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
49099566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
49109566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
49119566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4912efd51863SBarry Smith       x = xnew;
4913efd51863SBarry Smith 
49149566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
49159566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
49169566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
49179566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
49189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4919efd51863SBarry Smith     }
4920efd51863SBarry Smith   }
49219566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
49229566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
49239566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
49249566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
49253f7e2da0SPeter Brune 
49269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
49279566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
49283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49299b94acceSBarry Smith }
49309b94acceSBarry Smith 
49319b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
49329b94acceSBarry Smith 
4933cc4c1da9SBarry Smith /*@
49340b4b7b1cSBarry Smith   SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES`
49359b94acceSBarry Smith 
4936c3339decSBarry Smith   Collective
4937fee21e36SBarry Smith 
4938c7afd0dbSLois Curfman McInnes   Input Parameters:
4939f6dfbefdSBarry Smith + snes - the `SNES` context
4940454a90a3SBarry Smith - type - a known method
4941c7afd0dbSLois Curfman McInnes 
4942c7afd0dbSLois Curfman McInnes   Options Database Key:
4943454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
494404d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4945ae12b187SLois Curfman McInnes 
4946dc4c0fb0SBarry Smith   Level: intermediate
4947dc4c0fb0SBarry Smith 
49489b94acceSBarry Smith   Notes:
49490b4b7b1cSBarry Smith   See `SNESType` for available methods (for instance)
4950f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4951c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49524a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4953c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49549b94acceSBarry Smith 
4955f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4956f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4957ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4958ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4959f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4960ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4961ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4962ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4963ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4964b0a32e0cSBarry Smith   appropriate method.
496536851e7fSLois Curfman McInnes 
4966420bcc1bSBarry Smith   Developer Note:
4967f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4968f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
49698f6c3df8SBarry Smith 
49701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49719b94acceSBarry Smith @*/
4972d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4973d71ae5a4SJacob Faibussowitsch {
4974ace3abfcSBarry Smith   PetscBool match;
49755f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
49763a40ed3dSBarry Smith 
49773a40ed3dSBarry Smith   PetscFunctionBegin;
49780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49794f572ea9SToby Isaac   PetscAssertPointer(type, 2);
498082bf6240SBarry Smith 
49819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
49823ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
498392ff6ae8SBarry Smith 
49849566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
49856adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
498675396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4987dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
498843547594SStefano Zampini   /* Reinitialize type-specific function pointers in SNESOps structure */
498943547594SStefano Zampini   snes->ops->reset          = NULL;
49909e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
49919e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
49929e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
49939e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
49949e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
49957fe760d5SStefano Zampini 
49967fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
49979566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
49987fe760d5SStefano Zampini 
499975396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
500075396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
5001f5af7f23SKarl Rupp 
50029566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
50039566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
50043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50059b94acceSBarry Smith }
50069b94acceSBarry Smith 
5007cc4c1da9SBarry Smith /*@
5008f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
50099b94acceSBarry Smith 
5010c7afd0dbSLois Curfman McInnes   Not Collective
5011c7afd0dbSLois Curfman McInnes 
50129b94acceSBarry Smith   Input Parameter:
50134b0e389bSBarry Smith . snes - nonlinear solver context
50149b94acceSBarry Smith 
50159b94acceSBarry Smith   Output Parameter:
5016f6dfbefdSBarry Smith . type - `SNES` method (a character string)
50179b94acceSBarry Smith 
501836851e7fSLois Curfman McInnes   Level: intermediate
501936851e7fSLois Curfman McInnes 
50201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
50219b94acceSBarry Smith @*/
5022d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
5023d71ae5a4SJacob Faibussowitsch {
50243a40ed3dSBarry Smith   PetscFunctionBegin;
50250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50264f572ea9SToby Isaac   PetscAssertPointer(type, 2);
50277adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
50283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50299b94acceSBarry Smith }
50309b94acceSBarry Smith 
50313cd8a7caSMatthew G. Knepley /*@
5032f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
50333cd8a7caSMatthew G. Knepley 
5034c3339decSBarry Smith   Logically Collective
50353cd8a7caSMatthew G. Knepley 
50363cd8a7caSMatthew G. Knepley   Input Parameters:
5037f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
50383cd8a7caSMatthew G. Knepley - u    - the solution vector
50393cd8a7caSMatthew G. Knepley 
50403cd8a7caSMatthew G. Knepley   Level: beginner
50413cd8a7caSMatthew G. Knepley 
50421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
50433cd8a7caSMatthew G. Knepley @*/
5044d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5045d71ae5a4SJacob Faibussowitsch {
50463cd8a7caSMatthew G. Knepley   DM dm;
50473cd8a7caSMatthew G. Knepley 
50483cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
50493cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50503cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50519566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
50529566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
50533cd8a7caSMatthew G. Knepley 
50543cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
50553cd8a7caSMatthew G. Knepley 
50569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50579566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
50583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50593cd8a7caSMatthew G. Knepley }
50603cd8a7caSMatthew G. Knepley 
506152baeb72SSatish Balay /*@
50629b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
5063f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50649b94acceSBarry Smith 
5065420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5066c7afd0dbSLois Curfman McInnes 
50679b94acceSBarry Smith   Input Parameter:
5068f6dfbefdSBarry Smith . snes - the `SNES` context
50699b94acceSBarry Smith 
50709b94acceSBarry Smith   Output Parameter:
50719b94acceSBarry Smith . x - the solution
50729b94acceSBarry Smith 
507370e92668SMatthew Knepley   Level: intermediate
507436851e7fSLois Curfman McInnes 
50751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
50769b94acceSBarry Smith @*/
5077d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5078d71ae5a4SJacob Faibussowitsch {
50793a40ed3dSBarry Smith   PetscFunctionBegin;
50800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50814f572ea9SToby Isaac   PetscAssertPointer(x, 2);
508285385478SLisandro Dalcin   *x = snes->vec_sol;
50833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
508470e92668SMatthew Knepley }
508570e92668SMatthew Knepley 
508652baeb72SSatish Balay /*@
50879b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
50889b94acceSBarry Smith   stored.
50899b94acceSBarry Smith 
5090420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5091c7afd0dbSLois Curfman McInnes 
50929b94acceSBarry Smith   Input Parameter:
5093f6dfbefdSBarry Smith . snes - the `SNES` context
50949b94acceSBarry Smith 
50959b94acceSBarry Smith   Output Parameter:
50969b94acceSBarry Smith . x - the solution update
50979b94acceSBarry Smith 
509836851e7fSLois Curfman McInnes   Level: advanced
509936851e7fSLois Curfman McInnes 
51001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
51019b94acceSBarry Smith @*/
5102d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5103d71ae5a4SJacob Faibussowitsch {
51043a40ed3dSBarry Smith   PetscFunctionBegin;
51050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51064f572ea9SToby Isaac   PetscAssertPointer(x, 2);
510785385478SLisandro Dalcin   *x = snes->vec_sol_update;
51083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51099b94acceSBarry Smith }
51109b94acceSBarry Smith 
51119b94acceSBarry Smith /*@C
5112f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
51139b94acceSBarry Smith 
5114420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5115c7afd0dbSLois Curfman McInnes 
51169b94acceSBarry Smith   Input Parameter:
5117f6dfbefdSBarry Smith . snes - the `SNES` context
51189b94acceSBarry Smith 
5119d8d19677SJose E. Roman   Output Parameters:
5120dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
51218434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5122dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
51239b94acceSBarry Smith 
512436851e7fSLois Curfman McInnes   Level: advanced
512536851e7fSLois Curfman McInnes 
5126f6dfbefdSBarry Smith   Note:
5127dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
512804edfde5SBarry Smith 
51298434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
51309b94acceSBarry Smith @*/
51318434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5132d71ae5a4SJacob Faibussowitsch {
51336cab3a1bSJed Brown   DM dm;
5134a63bb30eSJed Brown 
51353a40ed3dSBarry Smith   PetscFunctionBegin;
51360700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5137a63bb30eSJed Brown   if (r) {
5138a63bb30eSJed Brown     if (!snes->vec_func) {
5139a63bb30eSJed Brown       if (snes->vec_rhs) {
51409566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5141a63bb30eSJed Brown       } else if (snes->vec_sol) {
51429566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5143a63bb30eSJed Brown       } else if (snes->dm) {
51449566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5145a63bb30eSJed Brown       }
5146a63bb30eSJed Brown     }
5147a63bb30eSJed Brown     *r = snes->vec_func;
5148a63bb30eSJed Brown   }
51499566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51509566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
51513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51529b94acceSBarry Smith }
51539b94acceSBarry Smith 
5154c79ef259SPeter Brune /*@C
515537fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5156c79ef259SPeter Brune 
5157c79ef259SPeter Brune   Input Parameter:
5158f6dfbefdSBarry Smith . snes - the `SNES` context
5159c79ef259SPeter Brune 
5160d8d19677SJose E. Roman   Output Parameters:
51618434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5162dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5163c79ef259SPeter Brune 
5164c79ef259SPeter Brune   Level: advanced
5165c79ef259SPeter Brune 
51668434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5167c79ef259SPeter Brune @*/
51688434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5169d71ae5a4SJacob Faibussowitsch {
51706cab3a1bSJed Brown   DM dm;
51716cab3a1bSJed Brown 
5172646217ecSPeter Brune   PetscFunctionBegin;
5173646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51749566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51759566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
51763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5177646217ecSPeter Brune }
5178646217ecSPeter Brune 
5179cc4c1da9SBarry Smith /*@
51803c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5181f6dfbefdSBarry Smith   `SNES` options in the database.
51823c7409f5SSatish Balay 
5183c3339decSBarry Smith   Logically Collective
5184fee21e36SBarry Smith 
5185d8d19677SJose E. Roman   Input Parameters:
5186f6dfbefdSBarry Smith + snes   - the `SNES` context
5187c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5188c7afd0dbSLois Curfman McInnes 
5189dc4c0fb0SBarry Smith   Level: advanced
5190dc4c0fb0SBarry Smith 
5191f6dfbefdSBarry Smith   Note:
5192a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5193c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5194d850072dSLois Curfman McInnes 
51951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
51963c7409f5SSatish Balay @*/
5197d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5198d71ae5a4SJacob Faibussowitsch {
51993a40ed3dSBarry Smith   PetscFunctionBegin;
52000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52019566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
52029566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
520335f5d045SPeter Brune   if (snes->linesearch) {
52049566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52059566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
520635f5d045SPeter Brune   }
52079566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
52083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52093c7409f5SSatish Balay }
52103c7409f5SSatish Balay 
5211cc4c1da9SBarry Smith /*@
5212f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5213f6dfbefdSBarry Smith   `SNES` options in the database.
52143c7409f5SSatish Balay 
5215c3339decSBarry Smith   Logically Collective
5216fee21e36SBarry Smith 
5217c7afd0dbSLois Curfman McInnes   Input Parameters:
5218f6dfbefdSBarry Smith + snes   - the `SNES` context
5219c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5220c7afd0dbSLois Curfman McInnes 
5221dc4c0fb0SBarry Smith   Level: advanced
5222dc4c0fb0SBarry Smith 
5223f6dfbefdSBarry Smith   Note:
5224a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5225c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5226d850072dSLois Curfman McInnes 
52271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
52283c7409f5SSatish Balay @*/
5229d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5230d71ae5a4SJacob Faibussowitsch {
52313a40ed3dSBarry Smith   PetscFunctionBegin;
52320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52339566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
52349566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
523535f5d045SPeter Brune   if (snes->linesearch) {
52369566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52379566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
523835f5d045SPeter Brune   }
52399566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
52403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52413c7409f5SSatish Balay }
52423c7409f5SSatish Balay 
5243cc4c1da9SBarry Smith /*@
5244f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5245f6dfbefdSBarry Smith   `SNES` options in the database.
52463c7409f5SSatish Balay 
5247c7afd0dbSLois Curfman McInnes   Not Collective
5248c7afd0dbSLois Curfman McInnes 
52493c7409f5SSatish Balay   Input Parameter:
5250f6dfbefdSBarry Smith . snes - the `SNES` context
52513c7409f5SSatish Balay 
52523c7409f5SSatish Balay   Output Parameter:
52533c7409f5SSatish Balay . prefix - pointer to the prefix string used
52543c7409f5SSatish Balay 
525536851e7fSLois Curfman McInnes   Level: advanced
525636851e7fSLois Curfman McInnes 
52571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52583c7409f5SSatish Balay @*/
5259d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5260d71ae5a4SJacob Faibussowitsch {
52613a40ed3dSBarry Smith   PetscFunctionBegin;
52620700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52639566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52653c7409f5SSatish Balay }
52663c7409f5SSatish Balay 
52673cea93caSBarry Smith /*@C
52681c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
52691c84c290SBarry Smith 
527020f4b53cSBarry Smith   Not Collective
52711c84c290SBarry Smith 
52721c84c290SBarry Smith   Input Parameters:
527320f4b53cSBarry Smith + sname    - name of a new user-defined solver
527420f4b53cSBarry Smith - function - routine to create method context
52751c84c290SBarry Smith 
5276dc4c0fb0SBarry Smith   Level: advanced
5277dc4c0fb0SBarry Smith 
5278f6dfbefdSBarry Smith   Note:
5279f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
52801c84c290SBarry Smith 
5281e4094ef1SJacob Faibussowitsch   Example Usage:
52821c84c290SBarry Smith .vb
5283bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
52841c84c290SBarry Smith .ve
52851c84c290SBarry Smith 
52861c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
5287b44f4de4SBarry Smith .vb
5288b44f4de4SBarry Smith   SNESSetType(snes, "my_solver")
5289b44f4de4SBarry Smith .ve
52901c84c290SBarry Smith   or at runtime via the option
5291b44f4de4SBarry Smith .vb
5292b44f4de4SBarry Smith   -snes_type my_solver
5293b44f4de4SBarry Smith .ve
52941c84c290SBarry Smith 
52951cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
52963cea93caSBarry Smith @*/
5297d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5298d71ae5a4SJacob Faibussowitsch {
5299b2002411SLois Curfman McInnes   PetscFunctionBegin;
53009566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
53019566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
53023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5303b2002411SLois Curfman McInnes }
5304da9b6338SBarry Smith 
5305d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5306d71ae5a4SJacob Faibussowitsch {
530777431f27SBarry Smith   PetscInt    N, i, j;
5308da9b6338SBarry Smith   Vec         u, uh, fh;
5309da9b6338SBarry Smith   PetscScalar value;
5310da9b6338SBarry Smith   PetscReal   norm;
5311da9b6338SBarry Smith 
5312da9b6338SBarry Smith   PetscFunctionBegin;
53139566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
53149566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
53159566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5316da9b6338SBarry Smith 
5317da9b6338SBarry Smith   /* currently only works for sequential */
53189566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
53199566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5320da9b6338SBarry Smith   for (i = 0; i < N; i++) {
53219566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
532263a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5323da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
53248b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
53259566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
53269566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
53279566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
532863a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5329da9b6338SBarry Smith       value = -value;
53309566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5331da9b6338SBarry Smith     }
5332da9b6338SBarry Smith   }
53339566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
53349566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
53353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5336da9b6338SBarry Smith }
533771f87433Sdalcinl 
533871f87433Sdalcinl /*@
5339f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
534071f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
534171f87433Sdalcinl   Newton method.
534271f87433Sdalcinl 
5343c3339decSBarry Smith   Logically Collective
534471f87433Sdalcinl 
534571f87433Sdalcinl   Input Parameters:
5346f6dfbefdSBarry Smith + snes - `SNES` context
5347f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
534871f87433Sdalcinl 
5349f6dfbefdSBarry Smith   Options Database Keys:
535064ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
535164ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
535264ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
535364ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
535464ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
535564ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
535664ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
535764ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
535864ba62caSBarry Smith 
5359dc4c0fb0SBarry Smith   Level: advanced
5360dc4c0fb0SBarry Smith 
5361f6dfbefdSBarry Smith   Note:
5362f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
536371f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
53641d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
536571f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
536671f87433Sdalcinl   solver.
536771f87433Sdalcinl 
53681cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
536971f87433Sdalcinl @*/
5370d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5371d71ae5a4SJacob Faibussowitsch {
537271f87433Sdalcinl   PetscFunctionBegin;
53730700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5374acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
537571f87433Sdalcinl   snes->ksp_ewconv = flag;
53763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
537771f87433Sdalcinl }
537871f87433Sdalcinl 
537971f87433Sdalcinl /*@
5380f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
538171f87433Sdalcinl   for computing relative tolerance for linear solvers within an
538271f87433Sdalcinl   inexact Newton method.
538371f87433Sdalcinl 
538471f87433Sdalcinl   Not Collective
538571f87433Sdalcinl 
538671f87433Sdalcinl   Input Parameter:
5387f6dfbefdSBarry Smith . snes - `SNES` context
538871f87433Sdalcinl 
538971f87433Sdalcinl   Output Parameter:
5390f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
539171f87433Sdalcinl 
539271f87433Sdalcinl   Level: advanced
539371f87433Sdalcinl 
53941cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
539571f87433Sdalcinl @*/
5396d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5397d71ae5a4SJacob Faibussowitsch {
539871f87433Sdalcinl   PetscFunctionBegin;
53990700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54004f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
540171f87433Sdalcinl   *flag = snes->ksp_ewconv;
54023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
540371f87433Sdalcinl }
540471f87433Sdalcinl 
540571f87433Sdalcinl /*@
5406fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
540771f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
540871f87433Sdalcinl   Newton method.
540971f87433Sdalcinl 
5410c3339decSBarry Smith   Logically Collective
541171f87433Sdalcinl 
541271f87433Sdalcinl   Input Parameters:
5413f6dfbefdSBarry Smith + snes      - `SNES` context
54140f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
541571f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
541671f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
541771f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
541871f87433Sdalcinl              (0 <= gamma2 <= 1)
541971f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
542071f87433Sdalcinl . alpha2    - power for safeguard
542171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
542271f87433Sdalcinl 
5423dc4c0fb0SBarry Smith   Level: advanced
5424dc4c0fb0SBarry Smith 
5425f6dfbefdSBarry Smith   Notes:
542671f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
542771f87433Sdalcinl 
542877e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
542971f87433Sdalcinl 
54301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
543171f87433Sdalcinl @*/
5432d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5433d71ae5a4SJacob Faibussowitsch {
5434fa9f3622SBarry Smith   SNESKSPEW *kctx;
54355fd66863SKarl Rupp 
543671f87433Sdalcinl   PetscFunctionBegin;
54370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5438fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54395f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5440c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5441c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5442c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5443c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5444c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5445c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5446c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
544771f87433Sdalcinl 
544877e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
544977e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
545077e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
545177e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
545277e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
545377e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
545477e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
545571f87433Sdalcinl 
54560f0abf79SStefano 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);
54570b121fc5SBarry 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);
54580b121fc5SBarry 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);
54590b121fc5SBarry 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);
54600b121fc5SBarry 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);
54610b121fc5SBarry 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);
54623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546371f87433Sdalcinl }
546471f87433Sdalcinl 
546571f87433Sdalcinl /*@
5466fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
546771f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
546871f87433Sdalcinl   Newton method.
546971f87433Sdalcinl 
547071f87433Sdalcinl   Not Collective
547171f87433Sdalcinl 
547297bb3fdcSJose E. Roman   Input Parameter:
5473f6dfbefdSBarry Smith . snes - `SNES` context
547471f87433Sdalcinl 
547571f87433Sdalcinl   Output Parameters:
54760f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
547771f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
547871f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5479bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
548071f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
548171f87433Sdalcinl . alpha2    - power for safeguard
548271f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
548371f87433Sdalcinl 
548471f87433Sdalcinl   Level: advanced
548571f87433Sdalcinl 
54861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
548771f87433Sdalcinl @*/
5488d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5489d71ae5a4SJacob Faibussowitsch {
5490fa9f3622SBarry Smith   SNESKSPEW *kctx;
54915fd66863SKarl Rupp 
549271f87433Sdalcinl   PetscFunctionBegin;
54930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5494fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54955f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
549671f87433Sdalcinl   if (version) *version = kctx->version;
549771f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
549871f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
549971f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
550071f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
550171f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
550271f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
55033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
550471f87433Sdalcinl }
550571f87433Sdalcinl 
55065c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5507d71ae5a4SJacob Faibussowitsch {
55085c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5509fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
551077e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
551171f87433Sdalcinl 
551271f87433Sdalcinl   PetscFunctionBegin;
55133ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
551430058271SDmitry Karpeev   if (!snes->iter) {
551530058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
55169566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
55170f0abf79SStefano Zampini   } else {
55180fdf79fbSJacob 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);
551971f87433Sdalcinl     if (kctx->version == 1) {
55200f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
552185ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
552271f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
552371f87433Sdalcinl     } else if (kctx->version == 2) {
552485ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
552585ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
552671f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
552771f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
552885ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
552971f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
553085ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
553171f87433Sdalcinl       stol = PetscMax(rtol, stol);
553271f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
553371f87433Sdalcinl       /* safeguard: avoid oversolving */
553430058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
553571f87433Sdalcinl       stol = PetscMax(rtol, stol);
553671f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
55370fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
55380fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
55390f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
55400f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
55410f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
55420f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
55430f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
55440f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
55450f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
55460f0abf79SStefano Zampini 
5547a4598233SStefano 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;
55480f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
55490f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
55500f0abf79SStefano Zampini       kctx->rk_last     = rk;
55510fdf79fbSJacob Faibussowitsch     }
55520f0abf79SStefano Zampini   }
55530f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
555471f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
555577e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
555663a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
55573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
555871f87433Sdalcinl }
555971f87433Sdalcinl 
55605c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5561d71ae5a4SJacob Faibussowitsch {
55625c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5563fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
556471f87433Sdalcinl   PCSide     pcside;
556571f87433Sdalcinl   Vec        lres;
556671f87433Sdalcinl 
556771f87433Sdalcinl   PetscFunctionBegin;
55683ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
55699566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
557071dbe336SPeter Brune   kctx->norm_last = snes->norm;
55710f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
55724f00ce20SMatthew G. Knepley     PC        pc;
55730f0abf79SStefano Zampini     PetscBool getRes;
55744f00ce20SMatthew G. Knepley 
55759566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
55760f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
55770f0abf79SStefano Zampini     if (!getRes) {
55780f0abf79SStefano Zampini       KSPNormType normtype;
55790f0abf79SStefano Zampini 
55800f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
55810f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
55820f0abf79SStefano Zampini     }
55839566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
55840f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
55859566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
558671f87433Sdalcinl     } else {
558771f87433Sdalcinl       /* KSP residual is preconditioned residual */
558871f87433Sdalcinl       /* compute true linear residual norm */
55890f0abf79SStefano Zampini       Mat J;
55900f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
55919566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
55920f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
55939566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
55949566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
55959566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
559671f87433Sdalcinl     }
559771f87433Sdalcinl   }
55983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
559971f87433Sdalcinl }
560071f87433Sdalcinl 
5601d4211eb9SBarry Smith /*@
5602f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5603d4211eb9SBarry Smith 
5604420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5605d4211eb9SBarry Smith 
5606d4211eb9SBarry Smith   Input Parameter:
5607f6dfbefdSBarry Smith . snes - the `SNES` context
5608d4211eb9SBarry Smith 
5609d4211eb9SBarry Smith   Output Parameter:
5610f6dfbefdSBarry Smith . ksp - the `KSP` context
5611d4211eb9SBarry Smith 
5612dc4c0fb0SBarry Smith   Level: beginner
5613dc4c0fb0SBarry Smith 
5614d4211eb9SBarry Smith   Notes:
5615f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5616d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5617f6dfbefdSBarry Smith   `PC` contexts as well.
5618f6dfbefdSBarry Smith 
56190b4b7b1cSBarry 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.
5620d4211eb9SBarry Smith 
56211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5622d4211eb9SBarry Smith @*/
5623d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5624d71ae5a4SJacob Faibussowitsch {
562571f87433Sdalcinl   PetscFunctionBegin;
5626d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56274f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5628d4211eb9SBarry Smith 
5629d4211eb9SBarry Smith   if (!snes->ksp) {
56309566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
56319566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5632d4211eb9SBarry Smith 
56335c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
56345c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5635a5c2985bSBarry Smith 
56369566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
56379566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5638d4211eb9SBarry Smith   }
5639d4211eb9SBarry Smith   *ksp = snes->ksp;
56403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
564171f87433Sdalcinl }
56426c699258SBarry Smith 
5643af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
56446c699258SBarry Smith /*@
56450b4b7b1cSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners
56466c699258SBarry Smith 
5647c3339decSBarry Smith   Logically Collective
56486c699258SBarry Smith 
56496c699258SBarry Smith   Input Parameters:
56502a808120SBarry Smith + snes - the nonlinear solver context
5651420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5652dc4c0fb0SBarry Smith 
5653dc4c0fb0SBarry Smith   Level: intermediate
56546c699258SBarry Smith 
5655f6dfbefdSBarry Smith   Note:
5656f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5657f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5658e03a659cSJed Brown   problems using the same function space.
5659e03a659cSJed Brown 
5660420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
56616c699258SBarry Smith @*/
5662d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5663d71ae5a4SJacob Faibussowitsch {
5664345fed2cSBarry Smith   KSP    ksp;
5665942e3340SBarry Smith   DMSNES sdm;
56666c699258SBarry Smith 
56676c699258SBarry Smith   PetscFunctionBegin;
56680700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56692a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
56709566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5671942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
567251f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
56739566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
56749566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5675f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
56766cab3a1bSJed Brown     }
56779566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
56789566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
56796cab3a1bSJed Brown   }
56806c699258SBarry Smith   snes->dm     = dm;
5681116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5682f5af7f23SKarl Rupp 
56839566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
56849566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
56859566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5686efd4aadfSBarry Smith   if (snes->npc) {
56879566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
56889566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
56892c155ee1SBarry Smith   }
56903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56916c699258SBarry Smith }
56926c699258SBarry Smith 
56936c699258SBarry Smith /*@
56940b4b7b1cSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners
56956c699258SBarry Smith 
56960b4b7b1cSBarry Smith   Not Collective but `dm` obtained is parallel on `snes`
56976c699258SBarry Smith 
56986c699258SBarry Smith   Input Parameter:
5699420bcc1bSBarry Smith . snes - the `SNES` context
57006c699258SBarry Smith 
57016c699258SBarry Smith   Output Parameter:
5702420bcc1bSBarry Smith . dm - the `DM`
57036c699258SBarry Smith 
57046c699258SBarry Smith   Level: intermediate
57056c699258SBarry Smith 
5706420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
57076c699258SBarry Smith @*/
5708d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5709d71ae5a4SJacob Faibussowitsch {
57106c699258SBarry Smith   PetscFunctionBegin;
57110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57126cab3a1bSJed Brown   if (!snes->dm) {
57139566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5714116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
57156cab3a1bSJed Brown   }
57166c699258SBarry Smith   *dm = snes->dm;
57173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57186c699258SBarry Smith }
57190807856dSBarry Smith 
572031823bd8SMatthew G Knepley /*@
5721be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
572231823bd8SMatthew G Knepley 
5723c3339decSBarry Smith   Collective
572431823bd8SMatthew G Knepley 
572531823bd8SMatthew G Knepley   Input Parameters:
5726f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
572762842358SBarry Smith - npc  - the `SNES` nonlinear preconditioner object
572862842358SBarry Smith 
572962842358SBarry Smith   Options Database Key:
573062842358SBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
573131823bd8SMatthew G Knepley 
5732dc4c0fb0SBarry Smith   Level: developer
5733dc4c0fb0SBarry Smith 
573431823bd8SMatthew G Knepley   Notes:
573562842358SBarry Smith   This is rarely used, rather use `SNESGetNPC()` to retrieve the preconditioner and configure it using the API.
573631823bd8SMatthew G Knepley 
5737f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5738f6dfbefdSBarry Smith 
5739420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
574031823bd8SMatthew G Knepley @*/
5741d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5742d71ae5a4SJacob Faibussowitsch {
574331823bd8SMatthew G Knepley   PetscFunctionBegin;
574431823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5745f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5746f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5747f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
57489566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5749f6dfbefdSBarry Smith   snes->npc = npc;
57503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
575131823bd8SMatthew G Knepley }
575231823bd8SMatthew G Knepley 
575331823bd8SMatthew G Knepley /*@
5754f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
575531823bd8SMatthew G Knepley 
57560b4b7b1cSBarry Smith   Not Collective; but any changes to the obtained the `pc` object must be applied collectively
575731823bd8SMatthew G Knepley 
575831823bd8SMatthew G Knepley   Input Parameter:
5759f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
576031823bd8SMatthew G Knepley 
576131823bd8SMatthew G Knepley   Output Parameter:
576262842358SBarry Smith . pc - the `SNES` preconditioner context
576331823bd8SMatthew G Knepley 
5764f6dfbefdSBarry Smith   Options Database Key:
5765f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5766b5badacbSBarry Smith 
57670b4b7b1cSBarry Smith   Level: advanced
5768dc4c0fb0SBarry Smith 
576995452b02SPatrick Sanan   Notes:
57700b4b7b1cSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will
57710b4b7b1cSBarry Smith   be used as the nonlinear preconditioner for the current `SNES`.
5772be95d8f1SBarry Smith 
5773f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
577462842358SBarry Smith   `SNES`. These may be overwritten if needed.
577562842358SBarry Smith 
577662842358SBarry Smith   Use the options database prefixes `-npc_snes`, `-npc_ksp`, etc., to control the configuration of the nonlinear preconditioner
5777951fe5abSBarry Smith 
57781cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
577931823bd8SMatthew G Knepley @*/
5780d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5781d71ae5a4SJacob Faibussowitsch {
5782a64e098fSPeter Brune   const char *optionsprefix;
578331823bd8SMatthew G Knepley 
578431823bd8SMatthew G Knepley   PetscFunctionBegin;
578531823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57864f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5787efd4aadfSBarry Smith   if (!snes->npc) {
5788ec785e5bSStefano Zampini     void *ctx;
5789ec785e5bSStefano Zampini 
57909566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
57919566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
57929566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57939566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
57949566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5795fb87a551SStefano Zampini     if (snes->ops->usercompute) {
579649abdd8aSBarry Smith       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy));
5797fb87a551SStefano Zampini     } else {
5798ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5799ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5800fb87a551SStefano Zampini     }
58019566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
580231823bd8SMatthew G Knepley   }
5803efd4aadfSBarry Smith   *pc = snes->npc;
58043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
580531823bd8SMatthew G Knepley }
580631823bd8SMatthew G Knepley 
58073ad1a0b9SPatrick Farrell /*@
58080b4b7b1cSBarry Smith   SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES`
58093ad1a0b9SPatrick Farrell 
58103ad1a0b9SPatrick Farrell   Not Collective
58113ad1a0b9SPatrick Farrell 
58123ad1a0b9SPatrick Farrell   Input Parameter:
5813f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58143ad1a0b9SPatrick Farrell 
58153ad1a0b9SPatrick Farrell   Output Parameter:
5816420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
58173ad1a0b9SPatrick Farrell 
58183ad1a0b9SPatrick Farrell   Level: developer
58193ad1a0b9SPatrick Farrell 
58201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
58213ad1a0b9SPatrick Farrell @*/
5822d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5823d71ae5a4SJacob Faibussowitsch {
58243ad1a0b9SPatrick Farrell   PetscFunctionBegin;
58253ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5826835f2295SStefano Zampini   PetscAssertPointer(has_npc, 2);
5827835f2295SStefano Zampini   *has_npc = snes->npc ? PETSC_TRUE : PETSC_FALSE;
58283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58293ad1a0b9SPatrick Farrell }
58303ad1a0b9SPatrick Farrell 
5831c40d0f55SPeter Brune /*@
583262842358SBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side used by the nonlinear preconditioner inside `SNES`.
5833c40d0f55SPeter Brune 
5834c3339decSBarry Smith   Logically Collective
5835c40d0f55SPeter Brune 
5836c40d0f55SPeter Brune   Input Parameter:
5837f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5838c40d0f55SPeter Brune 
5839c40d0f55SPeter Brune   Output Parameter:
5840c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5841c40d0f55SPeter Brune .vb
58422d547940SBarry Smith       PC_LEFT  - left preconditioning
58432d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5844c40d0f55SPeter Brune .ve
5845c40d0f55SPeter Brune 
5846f6dfbefdSBarry Smith   Options Database Key:
584767b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5848c40d0f55SPeter Brune 
5849dc4c0fb0SBarry Smith   Level: intermediate
5850dc4c0fb0SBarry Smith 
5851f6dfbefdSBarry Smith   Note:
5852f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
58532d547940SBarry Smith 
585462842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5855c40d0f55SPeter Brune @*/
5856d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5857d71ae5a4SJacob Faibussowitsch {
5858c40d0f55SPeter Brune   PetscFunctionBegin;
5859c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5860c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5861b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
586254c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5863efd4aadfSBarry Smith   snes->npcside = side;
58643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5865c40d0f55SPeter Brune }
5866c40d0f55SPeter Brune 
5867c40d0f55SPeter Brune /*@
586862842358SBarry Smith   SNESGetNPCSide - Gets the preconditioning side used by the nonlinear preconditioner inside `SNES`.
5869c40d0f55SPeter Brune 
5870c40d0f55SPeter Brune   Not Collective
5871c40d0f55SPeter Brune 
5872c40d0f55SPeter Brune   Input Parameter:
5873f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5874c40d0f55SPeter Brune 
5875c40d0f55SPeter Brune   Output Parameter:
5876c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5877c40d0f55SPeter Brune .vb
5878f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5879f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5880c40d0f55SPeter Brune .ve
5881c40d0f55SPeter Brune 
5882c40d0f55SPeter Brune   Level: intermediate
5883c40d0f55SPeter Brune 
588462842358SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNPC()`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5885c40d0f55SPeter Brune @*/
5886d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5887d71ae5a4SJacob Faibussowitsch {
5888c40d0f55SPeter Brune   PetscFunctionBegin;
5889c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58904f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5891efd4aadfSBarry Smith   *side = snes->npcside;
58923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5893c40d0f55SPeter Brune }
5894c40d0f55SPeter Brune 
58959e764e56SPeter Brune /*@
58960b4b7b1cSBarry Smith   SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES`
58979e764e56SPeter Brune 
5898c3339decSBarry Smith   Collective
58999e764e56SPeter Brune 
59009e764e56SPeter Brune   Input Parameters:
5901f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
59029e764e56SPeter Brune - linesearch - the linesearch object
59039e764e56SPeter Brune 
5904dc4c0fb0SBarry Smith   Level: developer
5905dc4c0fb0SBarry Smith 
5906f6dfbefdSBarry Smith   Note:
5907420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
59089e764e56SPeter Brune   to configure it using the API).
59099e764e56SPeter Brune 
5910420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
59119e764e56SPeter Brune @*/
5912d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5913d71ae5a4SJacob Faibussowitsch {
59149e764e56SPeter Brune   PetscFunctionBegin;
59159e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5916f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
59179e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
59189566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
59199566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5920f5af7f23SKarl Rupp 
59219e764e56SPeter Brune   snes->linesearch = linesearch;
59223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59239e764e56SPeter Brune }
59249e764e56SPeter Brune 
5925a34ceb2aSJed Brown /*@
592662842358SBarry Smith   SNESGetLineSearch - Returns the line search associated with the `SNES`.
59279e764e56SPeter Brune 
59289e764e56SPeter Brune   Not Collective
59299e764e56SPeter Brune 
59309e764e56SPeter Brune   Input Parameter:
5931f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
59329e764e56SPeter Brune 
59339e764e56SPeter Brune   Output Parameter:
59349e764e56SPeter Brune . linesearch - linesearch context
59359e764e56SPeter Brune 
5936162e0bf5SPeter Brune   Level: beginner
59379e764e56SPeter Brune 
593862842358SBarry Smith   Notes:
593962842358SBarry Smith   It creates a default line search instance which can be configured as needed in case it has not been already set with `SNESSetLineSearch()`.
594062842358SBarry Smith 
594162842358SBarry Smith   You can also use the options database keys `-snes_linesearch_*` to configure the line search. See `SNESLineSearchSetFromOptions()` for the possible options.
594262842358SBarry Smith 
594362842358SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`, `SNESLineSearchSetFromOptions()`
59449e764e56SPeter Brune @*/
5945d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5946d71ae5a4SJacob Faibussowitsch {
59479e764e56SPeter Brune   const char *optionsprefix;
59489e764e56SPeter Brune 
59499e764e56SPeter Brune   PetscFunctionBegin;
59509e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59514f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
59529e764e56SPeter Brune   if (!snes->linesearch) {
59539566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
59549566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
59559566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
59569566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
59579566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
59589e764e56SPeter Brune   }
59599e764e56SPeter Brune   *linesearch = snes->linesearch;
59603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59619e764e56SPeter Brune }
5962