xref: /petsc/src/snes/interface/snes.c (revision 97d931d150b06dfedbc17fbc85fb6d2592bf33cf)
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;
13fc8bc0e3SRichard Tran Mills PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, 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 
27455849f57SBarry Smith /*@C
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 
324fe2efc57SMark /*@C
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 
3487e2c5f70SBarry Smith /*@C
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     }
41963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
4209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42148a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4239566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4249566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
42548a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4269b94acceSBarry Smith     if (snes->ksp_ewconv) {
427fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4289b94acceSBarry Smith       if (kctx) {
42963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4329b94acceSBarry Smith       }
4339b94acceSBarry Smith     }
434eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
436eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
43763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
438eb1f6c34SBarry Smith     }
439eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
441eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
44263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
443eb1f6c34SBarry Smith     }
4449566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4459566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
446789d8953SBarry Smith     if (snes->mf_operator) {
4479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
448789d8953SBarry Smith       pre = "Preconditioning ";
449789d8953SBarry Smith     }
4508404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4528404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
454789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
455789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
456789d8953SBarry Smith       MatFDColoring fdcoloring;
4579566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
458789d8953SBarry Smith       if (fdcoloring) {
4599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
460789d8953SBarry Smith       } else {
4619566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
462789d8953SBarry Smith       }
463996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4658404b7f3SBarry Smith     }
4660f5bd95cSBarry Smith   } else if (isstring) {
467317d6ea6SBarry Smith     const char *type;
4689566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4699566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
470dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47155849f57SBarry Smith   } else if (isbinary) {
47255849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
47355849f57SBarry Smith     MPI_Comm    comm;
47455849f57SBarry Smith     PetscMPIInt rank;
47555849f57SBarry Smith     char        type[256];
47655849f57SBarry Smith 
4779566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
479dd400576SPatrick Sanan     if (rank == 0) {
4809566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4819566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4829566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48355849f57SBarry Smith     }
484dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
48572a02f06SBarry Smith   } else if (isdraw) {
48672a02f06SBarry Smith     PetscDraw draw;
48772a02f06SBarry Smith     char      str[36];
48889fd9fafSBarry Smith     PetscReal x, y, bottom, h;
48972a02f06SBarry Smith 
4909566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4919566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4929566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4939566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
4949566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
49589fd9fafSBarry Smith     bottom = y - h;
4969566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
497dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
498e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
499536b137fSBarry Smith   } else if (issaws) {
500d45a07a7SBarry Smith     PetscMPIInt rank;
5012657e9d9SBarry Smith     const char *name;
502d45a07a7SBarry Smith 
5039566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
505dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
506d45a07a7SBarry Smith       char dir[1024];
507d45a07a7SBarry Smith 
5089566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5099566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
510792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51148a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5129566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
513792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
514f05ece33SBarry Smith     }
515bfb97211SBarry Smith #endif
51672a02f06SBarry Smith   }
51772a02f06SBarry Smith   if (snes->linesearch) {
5189566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5209566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
52219bcc07fSBarry Smith   }
523efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5259566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5274a0c5b0cSMatthew G Knepley   }
5289566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5299566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5309566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5319566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5322c155ee1SBarry Smith   if (snes->usesksp) {
5339566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5359566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5372c155ee1SBarry Smith   }
53872a02f06SBarry Smith   if (isdraw) {
53972a02f06SBarry Smith     PetscDraw draw;
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5419566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5427f1410a3SPeter Brune   }
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5449b94acceSBarry Smith }
5459b94acceSBarry Smith 
54676b2cf59SMatthew Knepley /*
54776b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
54876b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
54976b2cf59SMatthew Knepley */
55076b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
551a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5526849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55376b2cf59SMatthew Knepley 
554ac226902SBarry Smith /*@C
555f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
55676b2cf59SMatthew Knepley 
55776b2cf59SMatthew Knepley   Not Collective
55876b2cf59SMatthew Knepley 
55976b2cf59SMatthew Knepley   Input Parameter:
56076b2cf59SMatthew Knepley . snescheck - function that checks for options
56176b2cf59SMatthew Knepley 
562420bcc1bSBarry Smith   Calling sequence of `snescheck`:
563420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
564420bcc1bSBarry Smith 
56576b2cf59SMatthew Knepley   Level: developer
56676b2cf59SMatthew Knepley 
5671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
56876b2cf59SMatthew Knepley @*/
569420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
570d71ae5a4SJacob Faibussowitsch {
57176b2cf59SMatthew Knepley   PetscFunctionBegin;
57263a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57376b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57576b2cf59SMatthew Knepley }
57676b2cf59SMatthew Knepley 
577d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
578d71ae5a4SJacob Faibussowitsch {
579aa3661deSLisandro Dalcin   Mat          J;
580895c21f2SBarry Smith   MatNullSpace nullsp;
581aa3661deSLisandro Dalcin 
582aa3661deSLisandro Dalcin   PetscFunctionBegin;
5830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
584aa3661deSLisandro Dalcin 
58598613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
58698613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5879566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
58898613b67SLisandro Dalcin   }
58998613b67SLisandro Dalcin 
5900fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
591aa3661deSLisandro Dalcin   if (version == 1) {
5929566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5939566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5949566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5951e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
5960fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
5975f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
598570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
599f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
600aa3661deSLisandro Dalcin #else
6012479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
602aa3661deSLisandro Dalcin #endif
6030fdf79fbSJacob Faibussowitsch   }
604aa3661deSLisandro Dalcin 
60501c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
606895c21f2SBarry Smith   if (snes->jacobian) {
6079566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6081baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
609895c21f2SBarry Smith   }
610895c21f2SBarry Smith 
61163a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
612d3462f78SMatthew Knepley   if (hasOperator) {
613aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
614aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6159566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
616aa3661deSLisandro Dalcin   } else {
617aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
61801c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
619b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6209566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
621172a4300SPeter Brune     } else {
622789d8953SBarry Smith       KSP       ksp;
623789d8953SBarry Smith       PC        pc;
624789d8953SBarry Smith       PetscBool match;
625789d8953SBarry Smith 
6269566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
627aa3661deSLisandro Dalcin       /* Force no preconditioner */
6289566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6299566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6302698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
631aa3661deSLisandro Dalcin       if (!match) {
6329566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6339566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
634aa3661deSLisandro Dalcin       }
635aa3661deSLisandro Dalcin     }
636789d8953SBarry Smith   }
6379566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
639aa3661deSLisandro Dalcin }
640aa3661deSLisandro Dalcin 
641d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
642d71ae5a4SJacob Faibussowitsch {
643dfe15315SJed Brown   SNES snes = (SNES)ctx;
6440298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
645dfe15315SJed Brown 
646dfe15315SJed Brown   PetscFunctionBegin;
64716ebb321SJed Brown   if (PetscLogPrintInfo) {
64816ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6499566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6509566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6519566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6529566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65363a3b9bcSJacob 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));
65416ebb321SJed Brown   }
655dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
656dfe15315SJed Brown   else {
6579566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
658dfe15315SJed Brown     Xfine = Xfine_named;
659dfe15315SJed Brown   }
6609566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
661907f5c5aSLawrence Mitchell   if (Inject) {
6629566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
663907f5c5aSLawrence Mitchell   } else {
6649566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6659566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
666907f5c5aSLawrence Mitchell   }
6679566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6689566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
670dfe15315SJed Brown }
671dfe15315SJed Brown 
672d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
673d71ae5a4SJacob Faibussowitsch {
67416ebb321SJed Brown   PetscFunctionBegin;
6759566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67716ebb321SJed Brown }
67816ebb321SJed Brown 
679a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
680a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
681d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
682d71ae5a4SJacob Faibussowitsch {
683caa4e7f2SJed Brown   SNES            snes = (SNES)ctx;
684*97d931d1SStefano Zampini   DMSNES          sdm;
6850298fd71SBarry Smith   Vec             X, Xnamed = NULL;
686dfe15315SJed Brown   DM              dmsave;
6874e269d77SPeter Brune   void           *ctxsave;
6888434afd1SBarry Smith   SNESJacobianFn *jac = NULL;
689caa4e7f2SJed Brown 
690caa4e7f2SJed Brown   PetscFunctionBegin;
691dfe15315SJed Brown   dmsave = snes->dm;
6929566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
693dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
694*97d931d1SStefano Zampini   else {
695*97d931d1SStefano Zampini     /* We are on a coarser level, this vec was initialized using a DM restrict hook */
696*97d931d1SStefano Zampini     PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
697dfe15315SJed Brown     X = Xnamed;
6989566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
6994e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
70048a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7014e269d77SPeter Brune   }
7024e269d77SPeter Brune 
7032b93b426SMatthew G. Knepley   /* Compute the operators */
704*97d931d1SStefano Zampini   PetscCall(DMGetDMSNES(snes->dm, &sdm));
705*97d931d1SStefano Zampini   if (Xnamed && sdm->ops->computefunction) {
706*97d931d1SStefano Zampini     /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
707*97d931d1SStefano Zampini        We make sure of this here. Disable affine shift since it is for the finest level */
708*97d931d1SStefano Zampini     Vec F, saverhs = snes->vec_rhs;
709*97d931d1SStefano Zampini 
710*97d931d1SStefano Zampini     snes->vec_rhs = NULL;
711*97d931d1SStefano Zampini     PetscCall(DMGetGlobalVector(snes->dm, &F));
712*97d931d1SStefano Zampini     PetscCall(SNESComputeFunction(snes, X, F));
713*97d931d1SStefano Zampini     PetscCall(DMRestoreGlobalVector(snes->dm, &F));
714*97d931d1SStefano Zampini     snes->vec_rhs = saverhs;
715*97d931d1SStefano Zampini     snes->nfuncs--; /* Do not log coarser level evaluations */
716*97d931d1SStefano Zampini   }
717*97d931d1SStefano Zampini   /* Make sure KSP DM has the Jacobian computation routine */
718*97d931d1SStefano Zampini   if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7199566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
720*97d931d1SStefano Zampini 
7212b93b426SMatthew G. Knepley   /* Put the previous context back */
72248a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7234e269d77SPeter Brune 
7249566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
725dfe15315SJed Brown   snes->dm = dmsave;
7263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
727caa4e7f2SJed Brown }
728caa4e7f2SJed Brown 
7296cab3a1bSJed Brown /*@
730dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7316cab3a1bSJed Brown 
7326cab3a1bSJed Brown   Collective
7336cab3a1bSJed Brown 
7344165533cSJose E. Roman   Input Parameter:
73520f4b53cSBarry Smith . snes - `SNES` object to configure
7366cab3a1bSJed Brown 
7376cab3a1bSJed Brown   Level: developer
7386cab3a1bSJed Brown 
739dc4c0fb0SBarry Smith   Note:
740dc4c0fb0SBarry 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`
741dc4c0fb0SBarry Smith 
74273a84a35SBarry Smith   Developer Note:
74373a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
74473a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
74573a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
74673a84a35SBarry Smith 
7471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7486cab3a1bSJed Brown @*/
749d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
750d71ae5a4SJacob Faibussowitsch {
7516cab3a1bSJed Brown   DM     dm;
752942e3340SBarry Smith   DMSNES sdm;
7536cab3a1bSJed Brown 
7546cab3a1bSJed Brown   PetscFunctionBegin;
7559566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7569566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
75773a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7586cab3a1bSJed Brown     Mat   J;
7596cab3a1bSJed Brown     void *functx;
7609566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7619566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7629566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7639566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7649566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
766caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7676cab3a1bSJed Brown     Mat J, B;
7689566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7699566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7709566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7719566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
77206f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7739566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7749566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
776caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7771ba9b98eSMatthew G. Knepley     PetscDS   prob;
7786cab3a1bSJed Brown     Mat       J, B;
7791ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7801ba9b98eSMatthew G. Knepley 
7816cab3a1bSJed Brown     J = snes->jacobian;
7829566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7839566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7849566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7859566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7869566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7879566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7889566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7899566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7906cab3a1bSJed Brown   }
791caa4e7f2SJed Brown   {
792caa4e7f2SJed Brown     KSP ksp;
7939566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
7949566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
7959566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
796caa4e7f2SJed Brown   }
7973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7986cab3a1bSJed Brown }
7996cab3a1bSJed Brown 
800d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
801d71ae5a4SJacob Faibussowitsch {
8025e7c47f3SMatthew G. Knepley   PetscInt i;
8035e7c47f3SMatthew G. Knepley 
8045e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8053ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
8065e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
8075e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
8085e7c47f3SMatthew G. Knepley     PetscDraw             draw;
8095e7c47f3SMatthew G. Knepley     PetscReal             lpause;
8105e7c47f3SMatthew G. Knepley 
8115e7c47f3SMatthew G. Knepley     if (!vf) continue;
8125e7c47f3SMatthew G. Knepley     if (vf->lg) {
8135e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
8145e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
8159566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
8169566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8179566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8189566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8199566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8205e7c47f3SMatthew G. Knepley     } else {
8215e7c47f3SMatthew G. Knepley       PetscBool isdraw;
8225e7c47f3SMatthew G. Knepley 
8235e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
8245e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
8259566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
8265e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
8279566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
8289566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8299566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8309566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8319566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8325e7c47f3SMatthew G. Knepley     }
8335e7c47f3SMatthew G. Knepley   }
8343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8355e7c47f3SMatthew G. Knepley }
8365e7c47f3SMatthew G. Knepley 
837fde5950dSBarry Smith /*@C
838fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
839fde5950dSBarry Smith 
840c3339decSBarry Smith   Collective
841fde5950dSBarry Smith 
842fde5950dSBarry Smith   Input Parameters:
843dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
844fde5950dSBarry Smith . name         - the monitor type one is seeking
845fde5950dSBarry Smith . help         - message indicating what monitoring is done
846fde5950dSBarry Smith . manual       - manual page for the monitor
847fde5950dSBarry Smith . monitor      - the monitor function
848f6dfbefdSBarry 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
849fde5950dSBarry Smith 
850420bcc1bSBarry Smith   Calling sequence of `monitor`:
851420bcc1bSBarry Smith + snes - the nonlinear solver context
852420bcc1bSBarry Smith . it   - the current iteration
853420bcc1bSBarry Smith . r    - the current function norm
854420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
855420bcc1bSBarry Smith 
856420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
857420bcc1bSBarry Smith + snes - the nonlinear solver context
858420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
859420bcc1bSBarry Smith 
860f6dfbefdSBarry Smith   Options Database Key:
861f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
862f6dfbefdSBarry Smith 
863f6dfbefdSBarry Smith   Level: advanced
864fde5950dSBarry Smith 
8651cc06b55SBarry Smith .seealso: [](ch_snes), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
866db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
867e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
868db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
869c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
870db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
871db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
872fde5950dSBarry Smith @*/
873420bcc1bSBarry 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))
874d71ae5a4SJacob Faibussowitsch {
875fde5950dSBarry Smith   PetscViewer       viewer;
876fde5950dSBarry Smith   PetscViewerFormat format;
877fde5950dSBarry Smith   PetscBool         flg;
878fde5950dSBarry Smith 
879fde5950dSBarry Smith   PetscFunctionBegin;
8809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
881fde5950dSBarry Smith   if (flg) {
882d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8839566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
884cd791dc2SBarry Smith     PetscCall(PetscOptionsRestoreViewer(&viewer));
8851baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8869566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
887fde5950dSBarry Smith   }
8883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
889fde5950dSBarry Smith }
890fde5950dSBarry Smith 
891a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
892d71ae5a4SJacob Faibussowitsch {
893a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
894a4598233SStefano Zampini 
8950f0abf79SStefano Zampini   PetscFunctionBegin;
8960f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
897a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
898a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
899a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
900a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
901a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
902a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
9030f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
904a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
9050f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
9060f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
9070f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
9080f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
9090f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
9100f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
9110f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
9120f0abf79SStefano Zampini   PetscOptionsEnd();
9133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9140f0abf79SStefano Zampini }
9150f0abf79SStefano Zampini 
9169b94acceSBarry Smith /*@
917f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9189b94acceSBarry Smith 
919c3339decSBarry Smith   Collective
920c7afd0dbSLois Curfman McInnes 
9219b94acceSBarry Smith   Input Parameter:
922f6dfbefdSBarry Smith . snes - the `SNES` context
9239b94acceSBarry Smith 
92436851e7fSLois Curfman McInnes   Options Database Keys:
925f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
926ceaaa498SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
92770441072SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
928b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
929e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
930ceaaa498SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
931b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
932b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
9334839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
934ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
935a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9363d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
937e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9383d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
9394a221d59SStefano Zampini . -snes_tr_tol <trtol>                                                         - trust region tolerance
940ceaaa498SBarry 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.
941fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
942fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
943fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
944fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9454619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
946459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9475e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
948e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
949e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
950ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
951b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
952ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
953e62ac41dSBarry 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.
954e62ac41dSBarry 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.
95582738288SBarry Smith 
956f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
957fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9584b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
95936851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
96036851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
96136851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
96236851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
96336851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
96436851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
96582738288SBarry Smith 
966dc4c0fb0SBarry Smith   Level: beginner
967dc4c0fb0SBarry Smith 
96811ca99fdSLois Curfman McInnes   Notes:
969ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
970ec5066bdSBarry Smith 
971420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
972420bcc1bSBarry Smith   and computing explicitly with
973f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
97483e2fdc7SBarry Smith 
975420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9769b94acceSBarry Smith @*/
977d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
978d71ae5a4SJacob Faibussowitsch {
9798afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
980d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
98104d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
982649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
98385385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9840f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
985c40d0f55SPeter Brune   PCSide      pcside;
986a64e098fSPeter Brune   const char *optionsprefix;
9879b94acceSBarry Smith 
9883a40ed3dSBarry Smith   PetscFunctionBegin;
9890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9909566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
991d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
992639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
994d64ed03dSBarry Smith   if (flg) {
9959566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9967adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9979566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
998d64ed03dSBarry Smith   }
9999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
10009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
1001186905e3SBarry Smith 
10029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
10039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
10049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
10059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
10069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
10079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
10089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
101185385478SLisandro Dalcin 
10129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1013a8054027SBarry Smith   if (flg) {
10145f80ce2aSJacob 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");
10159566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1016a8054027SBarry Smith   }
10179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10181baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1020e35cf81dSBarry Smith   if (flg) {
10215f80ce2aSJacob 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");
10229566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1023e35cf81dSBarry Smith   }
10249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10251baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
102637ec4e1aSPeter Brune 
10279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10281baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1029a8054027SBarry Smith 
1030400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
103185385478SLisandro Dalcin   if (flg) {
103285385478SLisandro Dalcin     switch (indx) {
1033d71ae5a4SJacob Faibussowitsch     case 0:
1034d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1035d71ae5a4SJacob Faibussowitsch       break;
1036d71ae5a4SJacob Faibussowitsch     case 1:
1037d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1038d71ae5a4SJacob Faibussowitsch       break;
1039d71ae5a4SJacob Faibussowitsch     case 2:
1040d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1041d71ae5a4SJacob Faibussowitsch       break;
104285385478SLisandro Dalcin     }
104385385478SLisandro Dalcin   }
104485385478SLisandro Dalcin 
10459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10469566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1047fdacfa88SPeter Brune 
10489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10499566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1050186905e3SBarry Smith 
105185385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
105285385478SLisandro Dalcin 
10539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1054186905e3SBarry Smith 
10550f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10560f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1057a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1058186905e3SBarry Smith 
105990d69ab7SBarry Smith   flg = PETSC_FALSE;
10609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10619566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1062eabae89aSBarry Smith 
10639566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10649566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10659566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1066eabae89aSBarry Smith 
10679566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10689566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10699566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10709566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10719566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10729566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10739566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10752db13446SMatthew G. Knepley 
10769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10779566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10785180491cSLisandro Dalcin 
107990d69ab7SBarry Smith   flg = PETSC_FALSE;
10809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1081459f5d12SBarry Smith   if (flg) {
1082459f5d12SBarry Smith     PetscViewer ctx;
1083e24b481bSBarry Smith 
10849566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10859566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1086459f5d12SBarry Smith   }
10872e7541e6SPeter Brune 
108890d69ab7SBarry Smith   flg = PETSC_FALSE;
10899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10909566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1091c4421ceaSFande Kong 
1092c4421ceaSFande Kong   flg = PETSC_FALSE;
10939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10944b27c08aSLois Curfman McInnes   if (flg) {
10956cab3a1bSJed Brown     void *functx;
1096b1f624c7SBarry Smith     DM    dm;
10979566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1098800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10999566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
11009566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
11019566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11029b94acceSBarry Smith   }
1103639f9d9dSBarry Smith 
110444848bc4SPeter Brune   flg = PETSC_FALSE;
11059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11061baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
110797584545SPeter Brune 
110897584545SPeter Brune   flg = PETSC_FALSE;
11099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
111044848bc4SPeter Brune   if (flg) {
1111c52e227fSPeter Brune     DM dm;
11129566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1113800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11149566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11159566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
111644848bc4SPeter Brune   }
111744848bc4SPeter Brune 
1118aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1120d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1121a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1122d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1123a8248277SBarry Smith   }
1124aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1126d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1128d28543b3SPeter Brune 
1129c40d0f55SPeter Brune   flg = PETSC_FALSE;
11309566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11329566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1133c40d0f55SPeter Brune 
1134e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11358a70d858SHong Zhang   /*
11368a70d858SHong Zhang     Publish convergence information using SAWs
11378a70d858SHong Zhang   */
11388a70d858SHong Zhang   flg = PETSC_FALSE;
11399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11408a70d858SHong Zhang   if (flg) {
11418a70d858SHong Zhang     void *ctx;
11429566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11439566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11448a70d858SHong Zhang   }
11458a70d858SHong Zhang #endif
11468a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1147b90c6cbeSBarry Smith   {
1148b90c6cbeSBarry Smith     PetscBool set;
1149b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11511baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1152b90c6cbeSBarry Smith   }
1153b90c6cbeSBarry Smith #endif
1154b90c6cbeSBarry Smith 
115548a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
115676b2cf59SMatthew Knepley 
1157dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11585d973c19SBarry Smith 
11595d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1160dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1161d0609cedSBarry Smith   PetscOptionsEnd();
11624bbc92c1SBarry Smith 
1163d8d34be6SBarry Smith   if (snes->linesearch) {
11649566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11659566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1166d8d34be6SBarry Smith   }
11679e764e56SPeter Brune 
11686aa5e7e9SBarry Smith   if (snes->usesksp) {
11699566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11709566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11719566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11726aa5e7e9SBarry Smith   }
11736991f827SBarry Smith 
1174b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11759566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
117748a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11781baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1179b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1181b3cd9a81SMatthew G. Knepley }
1182b3cd9a81SMatthew G. Knepley 
1183b3cd9a81SMatthew G. Knepley /*@
1184420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1185b3cd9a81SMatthew G. Knepley 
1186c3339decSBarry Smith   Collective
1187b3cd9a81SMatthew G. Knepley 
1188b3cd9a81SMatthew G. Knepley   Input Parameter:
1189f6dfbefdSBarry Smith . snes - the `SNES` context
1190b3cd9a81SMatthew G. Knepley 
1191420bcc1bSBarry Smith   Level: advanced
1192b3cd9a81SMatthew G. Knepley 
11931cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1194b3cd9a81SMatthew G. Knepley @*/
1195d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1196d71ae5a4SJacob Faibussowitsch {
1197b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11989566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12009b94acceSBarry Smith }
12019b94acceSBarry Smith 
1202bb9467b5SJed Brown /*@C
1203d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1204d25893d9SBarry Smith   the nonlinear solvers.
1205d25893d9SBarry Smith 
1206dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1207d25893d9SBarry Smith 
1208d25893d9SBarry Smith   Input Parameters:
1209f6dfbefdSBarry Smith + snes    - the `SNES` context
1210d25893d9SBarry Smith . compute - function to compute the context
1211d25893d9SBarry Smith - destroy - function to destroy the context
1212d25893d9SBarry Smith 
1213420bcc1bSBarry Smith   Calling sequence of `compute`:
1214420bcc1bSBarry Smith + snes - the `SNES` context
1215420bcc1bSBarry Smith - ctx  - context to be computed
1216420bcc1bSBarry Smith 
1217420bcc1bSBarry Smith   Calling sequence of `destroy`:
1218420bcc1bSBarry Smith . ctx - context to be computed by `compute()`
1219420bcc1bSBarry Smith 
1220d25893d9SBarry Smith   Level: intermediate
1221d25893d9SBarry Smith 
1222f6dfbefdSBarry Smith   Note:
1223f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1224f6dfbefdSBarry Smith 
1225f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1226f6dfbefdSBarry Smith 
122742747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`
1228d25893d9SBarry Smith @*/
1229420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx))
1230d71ae5a4SJacob Faibussowitsch {
1231d25893d9SBarry Smith   PetscFunctionBegin;
1232d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1233d25893d9SBarry Smith   snes->ops->usercompute = compute;
1234d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
12353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1236d25893d9SBarry Smith }
1237a847f771SSatish Balay 
1238b07ff414SBarry Smith /*@
1239f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12409b94acceSBarry Smith 
1241c3339decSBarry Smith   Logically Collective
1242fee21e36SBarry Smith 
1243c7afd0dbSLois Curfman McInnes   Input Parameters:
1244f6dfbefdSBarry Smith + snes - the `SNES` context
1245c7afd0dbSLois Curfman McInnes - usrP - optional user context
1246c7afd0dbSLois Curfman McInnes 
124736851e7fSLois Curfman McInnes   Level: intermediate
124836851e7fSLois Curfman McInnes 
1249f6dfbefdSBarry Smith   Notes:
1250f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1251f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1252f6dfbefdSBarry Smith 
1253f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1254f6dfbefdSBarry Smith 
1255420bcc1bSBarry Smith   Fortran Note:
1256dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1257420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1258daf670e6SBarry Smith 
12591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12609b94acceSBarry Smith @*/
1261d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1262d71ae5a4SJacob Faibussowitsch {
1263b07ff414SBarry Smith   KSP ksp;
12641b2093e4SBarry Smith 
12653a40ed3dSBarry Smith   PetscFunctionBegin;
12660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12679566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12689566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12699b94acceSBarry Smith   snes->user = usrP;
12703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12719b94acceSBarry Smith }
127274679c65SBarry Smith 
1273b07ff414SBarry Smith /*@
12749b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1275420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12769b94acceSBarry Smith 
1277c7afd0dbSLois Curfman McInnes   Not Collective
1278c7afd0dbSLois Curfman McInnes 
12799b94acceSBarry Smith   Input Parameter:
1280f6dfbefdSBarry Smith . snes - `SNES` context
12819b94acceSBarry Smith 
12829b94acceSBarry Smith   Output Parameter:
12839b94acceSBarry Smith . usrP - user context
12849b94acceSBarry Smith 
128536851e7fSLois Curfman McInnes   Level: intermediate
128636851e7fSLois Curfman McInnes 
1287420bcc1bSBarry Smith   Fortran Note:
1288dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1289420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1290dc4c0fb0SBarry Smith 
1291420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
12929b94acceSBarry Smith @*/
1293d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1294d71ae5a4SJacob Faibussowitsch {
12953a40ed3dSBarry Smith   PetscFunctionBegin;
12960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1297e71120c6SJed Brown   *(void **)usrP = snes->user;
12983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12999b94acceSBarry Smith }
130074679c65SBarry Smith 
13019b94acceSBarry Smith /*@
1302420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13033565c898SBarry Smith 
1304dc4c0fb0SBarry Smith   Logically Collective
13053565c898SBarry Smith 
13063565c898SBarry Smith   Input Parameters:
1307f6dfbefdSBarry Smith + snes        - `SNES` context
1308f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1309f6dfbefdSBarry 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
1310420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13113565c898SBarry Smith 
1312f6dfbefdSBarry Smith   Options Database Keys:
131301c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1314f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1315ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1316ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13173565c898SBarry Smith 
13183565c898SBarry Smith   Level: intermediate
13193565c898SBarry Smith 
1320f6dfbefdSBarry Smith   Note:
1321420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1322420bcc1bSBarry Smith   and computing explicitly with
1323f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1324ec5066bdSBarry Smith 
1325420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13263565c898SBarry Smith @*/
1327d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1328d71ae5a4SJacob Faibussowitsch {
13293565c898SBarry Smith   PetscFunctionBegin;
13303565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
133188b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
133288b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13334ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13343565c898SBarry Smith   snes->mf_operator = mf_operator;
13353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13363565c898SBarry Smith }
13373565c898SBarry Smith 
13383565c898SBarry Smith /*@
1339dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13403565c898SBarry Smith 
1341420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13423565c898SBarry Smith 
13433565c898SBarry Smith   Input Parameter:
1344f6dfbefdSBarry Smith . snes - `SNES` context
13453565c898SBarry Smith 
13463565c898SBarry Smith   Output Parameters:
1347f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1348f6dfbefdSBarry 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
13493565c898SBarry Smith 
13503565c898SBarry Smith   Level: intermediate
13513565c898SBarry Smith 
13521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13533565c898SBarry Smith @*/
1354d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1355d71ae5a4SJacob Faibussowitsch {
13563565c898SBarry Smith   PetscFunctionBegin;
13573565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13583565c898SBarry Smith   if (mf) *mf = snes->mf;
13593565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13613565c898SBarry Smith }
13623565c898SBarry Smith 
13633565c898SBarry Smith /*@
1364420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13659b94acceSBarry Smith 
1366c7afd0dbSLois Curfman McInnes   Not Collective
1367c7afd0dbSLois Curfman McInnes 
13689b94acceSBarry Smith   Input Parameter:
1369f6dfbefdSBarry Smith . snes - `SNES` context
13709b94acceSBarry Smith 
13719b94acceSBarry Smith   Output Parameter:
13729b94acceSBarry Smith . iter - iteration number
13739b94acceSBarry Smith 
1374dc4c0fb0SBarry Smith   Level: intermediate
1375dc4c0fb0SBarry Smith 
1376c8228a4eSBarry Smith   Notes:
1377c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1378c8228a4eSBarry Smith 
1379c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1380f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
138108405cd6SLois Curfman McInnes .vb
138208405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
138308405cd6SLois Curfman McInnes       if (!(it % 2)) {
138408405cd6SLois Curfman McInnes         [compute Jacobian here]
138508405cd6SLois Curfman McInnes       }
138608405cd6SLois Curfman McInnes .ve
1387f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1388f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1389c8228a4eSBarry Smith 
1390f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1391c04deec6SBarry Smith 
1392420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
13939b94acceSBarry Smith @*/
1394d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1395d71ae5a4SJacob Faibussowitsch {
13963a40ed3dSBarry Smith   PetscFunctionBegin;
13970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13984f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
13999b94acceSBarry Smith   *iter = snes->iter;
14003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14019b94acceSBarry Smith }
140274679c65SBarry Smith 
1403360c497dSPeter Brune /*@
1404360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1405360c497dSPeter Brune 
1406360c497dSPeter Brune   Not Collective
1407360c497dSPeter Brune 
1408d8d19677SJose E. Roman   Input Parameters:
1409f6dfbefdSBarry Smith + snes - `SNES` context
1410a2b725a8SWilliam Gropp - iter - iteration number
1411360c497dSPeter Brune 
1412360c497dSPeter Brune   Level: developer
1413360c497dSPeter Brune 
1414420bcc1bSBarry Smith   Note:
1415420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1416420bcc1bSBarry Smith 
14171cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1418360c497dSPeter Brune @*/
1419d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1420d71ae5a4SJacob Faibussowitsch {
1421360c497dSPeter Brune   PetscFunctionBegin;
1422360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14239566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1424360c497dSPeter Brune   snes->iter = iter;
14259566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1427360c497dSPeter Brune }
1428360c497dSPeter Brune 
14299b94acceSBarry Smith /*@
1430b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1431420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14329b94acceSBarry Smith 
1433c7afd0dbSLois Curfman McInnes   Not Collective
1434c7afd0dbSLois Curfman McInnes 
14359b94acceSBarry Smith   Input Parameter:
1436f6dfbefdSBarry Smith . snes - `SNES` context
14379b94acceSBarry Smith 
14389b94acceSBarry Smith   Output Parameter:
14399b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14409b94acceSBarry Smith 
1441dc4c0fb0SBarry Smith   Level: intermediate
1442dc4c0fb0SBarry Smith 
1443f6dfbefdSBarry Smith   Note:
1444f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1445c96a6f78SLois Curfman McInnes 
14461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1447db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14489b94acceSBarry Smith @*/
1449d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1450d71ae5a4SJacob Faibussowitsch {
14513a40ed3dSBarry Smith   PetscFunctionBegin;
14520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14534f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
145450ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145650ffb88aSMatthew Knepley }
145750ffb88aSMatthew Knepley 
145850ffb88aSMatthew Knepley /*@
1459b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1460420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
146150ffb88aSMatthew Knepley 
146250ffb88aSMatthew Knepley   Not Collective
146350ffb88aSMatthew Knepley 
146450ffb88aSMatthew Knepley   Input Parameters:
1465f6dfbefdSBarry Smith + snes     - `SNES` context
146650ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps
146750ffb88aSMatthew Knepley 
1468420bcc1bSBarry Smith   Options Database Key:
1469420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1470420bcc1bSBarry Smith 
147150ffb88aSMatthew Knepley   Level: intermediate
147250ffb88aSMatthew Knepley 
1473420bcc1bSBarry Smith   Developer Note:
1474420bcc1bSBarry Smith   The options database key is wrong for this function name
1475420bcc1bSBarry Smith 
14761cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1477db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
147850ffb88aSMatthew Knepley @*/
1479d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1480d71ae5a4SJacob Faibussowitsch {
148150ffb88aSMatthew Knepley   PetscFunctionBegin;
14820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
148350ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
14843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148550ffb88aSMatthew Knepley }
148650ffb88aSMatthew Knepley 
148750ffb88aSMatthew Knepley /*@
1488b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1489420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
149050ffb88aSMatthew Knepley 
149150ffb88aSMatthew Knepley   Not Collective
149250ffb88aSMatthew Knepley 
149350ffb88aSMatthew Knepley   Input Parameter:
149420f4b53cSBarry Smith . snes - `SNES` context
149550ffb88aSMatthew Knepley 
149650ffb88aSMatthew Knepley   Output Parameter:
149750ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
149850ffb88aSMatthew Knepley 
149950ffb88aSMatthew Knepley   Level: intermediate
150050ffb88aSMatthew Knepley 
15011cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1502db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
150350ffb88aSMatthew Knepley @*/
1504d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1505d71ae5a4SJacob Faibussowitsch {
150650ffb88aSMatthew Knepley   PetscFunctionBegin;
15070700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15084f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
150950ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15119b94acceSBarry Smith }
1512a847f771SSatish Balay 
15132541af92SBarry Smith /*@
15142541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1515420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15162541af92SBarry Smith 
15172541af92SBarry Smith   Not Collective
15182541af92SBarry Smith 
15192541af92SBarry Smith   Input Parameter:
1520f6dfbefdSBarry Smith . snes - `SNES` context
15212541af92SBarry Smith 
15222541af92SBarry Smith   Output Parameter:
15232541af92SBarry Smith . nfuncs - number of evaluations
15242541af92SBarry Smith 
15252541af92SBarry Smith   Level: intermediate
15262541af92SBarry Smith 
1527f6dfbefdSBarry Smith   Note:
1528f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1529971e163fSPeter Brune 
15301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15312541af92SBarry Smith @*/
1532d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1533d71ae5a4SJacob Faibussowitsch {
15342541af92SBarry Smith   PetscFunctionBegin;
15350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15364f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15372541af92SBarry Smith   *nfuncs = snes->nfuncs;
15383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15392541af92SBarry Smith }
15402541af92SBarry Smith 
15413d4c4710SBarry Smith /*@
15423d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1543420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15443d4c4710SBarry Smith 
15453d4c4710SBarry Smith   Not Collective
15463d4c4710SBarry Smith 
15473d4c4710SBarry Smith   Input Parameter:
1548f6dfbefdSBarry Smith . snes - `SNES` context
15493d4c4710SBarry Smith 
15503d4c4710SBarry Smith   Output Parameter:
15513d4c4710SBarry Smith . nfails - number of failed solves
15523d4c4710SBarry Smith 
1553f6dfbefdSBarry Smith   Options Database Key:
15549d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15559d85da0cSMatthew G. Knepley 
1556f6dfbefdSBarry Smith   Level: intermediate
1557f6dfbefdSBarry Smith 
1558f6dfbefdSBarry Smith   Note:
1559f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15603d4c4710SBarry Smith 
15611cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15623d4c4710SBarry Smith @*/
1563d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1564d71ae5a4SJacob Faibussowitsch {
15653d4c4710SBarry Smith   PetscFunctionBegin;
15660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15674f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15683d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15703d4c4710SBarry Smith }
15713d4c4710SBarry Smith 
15723d4c4710SBarry Smith /*@
15733d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1574f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15753d4c4710SBarry Smith 
1576c3339decSBarry Smith   Logically Collective
15773d4c4710SBarry Smith 
15783d4c4710SBarry Smith   Input Parameters:
1579f6dfbefdSBarry Smith + snes     - `SNES` context
15803d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures
15813d4c4710SBarry Smith 
1582f6dfbefdSBarry Smith   Options Database Key:
15839d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15849d85da0cSMatthew G. Knepley 
1585dc4c0fb0SBarry Smith   Level: intermediate
1586dc4c0fb0SBarry Smith 
1587f6dfbefdSBarry Smith   Note:
1588f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
15893d4c4710SBarry Smith 
1590420bcc1bSBarry Smith   Developer Note:
1591420bcc1bSBarry Smith   The options database key is wrong for this function name
1592420bcc1bSBarry Smith 
15931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
15943d4c4710SBarry Smith @*/
1595d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1596d71ae5a4SJacob Faibussowitsch {
15973d4c4710SBarry Smith   PetscFunctionBegin;
15980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1599c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
16003d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
16013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16023d4c4710SBarry Smith }
16033d4c4710SBarry Smith 
16043d4c4710SBarry Smith /*@
16053d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1606f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16073d4c4710SBarry Smith 
16083d4c4710SBarry Smith   Not Collective
16093d4c4710SBarry Smith 
16103d4c4710SBarry Smith   Input Parameter:
1611f6dfbefdSBarry Smith . snes - `SNES` context
16123d4c4710SBarry Smith 
16133d4c4710SBarry Smith   Output Parameter:
16143d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16153d4c4710SBarry Smith 
16163d4c4710SBarry Smith   Level: intermediate
16173d4c4710SBarry Smith 
1618f6dfbefdSBarry Smith   Note:
1619f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16203d4c4710SBarry Smith 
16211cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16223d4c4710SBarry Smith @*/
1623d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1624d71ae5a4SJacob Faibussowitsch {
16253d4c4710SBarry Smith   PetscFunctionBegin;
16260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16274f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16283d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16303d4c4710SBarry Smith }
16313d4c4710SBarry Smith 
1632c96a6f78SLois Curfman McInnes /*@
1633b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1634420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1635c96a6f78SLois Curfman McInnes 
1636c7afd0dbSLois Curfman McInnes   Not Collective
1637c7afd0dbSLois Curfman McInnes 
1638c96a6f78SLois Curfman McInnes   Input Parameter:
1639f6dfbefdSBarry Smith . snes - `SNES` context
1640c96a6f78SLois Curfman McInnes 
1641c96a6f78SLois Curfman McInnes   Output Parameter:
1642c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1643c96a6f78SLois Curfman McInnes 
1644dc4c0fb0SBarry Smith   Level: intermediate
1645dc4c0fb0SBarry Smith 
1646c96a6f78SLois Curfman McInnes   Notes:
1647f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1648c96a6f78SLois Curfman McInnes 
1649f6dfbefdSBarry 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
1650f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1651010be392SBarry Smith 
16521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1653c96a6f78SLois Curfman McInnes @*/
1654d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1655d71ae5a4SJacob Faibussowitsch {
16563a40ed3dSBarry Smith   PetscFunctionBegin;
16570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16584f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1659c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1661c96a6f78SLois Curfman McInnes }
1662c96a6f78SLois Curfman McInnes 
1663971e163fSPeter Brune /*@
1664971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1665f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1666971e163fSPeter Brune 
1667c3339decSBarry Smith   Logically Collective
1668971e163fSPeter Brune 
1669d8d19677SJose E. Roman   Input Parameters:
1670f6dfbefdSBarry Smith + snes  - `SNES` context
1671f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1672971e163fSPeter Brune 
1673971e163fSPeter Brune   Level: developer
1674971e163fSPeter Brune 
16751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1676971e163fSPeter Brune @*/
1677d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1678d71ae5a4SJacob Faibussowitsch {
1679971e163fSPeter Brune   PetscFunctionBegin;
1680971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1681971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1682971e163fSPeter Brune   snes->counters_reset = reset;
16833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1684971e163fSPeter Brune }
1685971e163fSPeter Brune 
16862999313aSBarry Smith /*@
1687f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16882999313aSBarry Smith 
1689420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
16902999313aSBarry Smith 
16912999313aSBarry Smith   Input Parameters:
1692f6dfbefdSBarry Smith + snes - the `SNES` context
1693f6dfbefdSBarry Smith - ksp  - the `KSP` context
16942999313aSBarry Smith 
1695dc4c0fb0SBarry Smith   Level: developer
1696dc4c0fb0SBarry Smith 
16972999313aSBarry Smith   Notes:
1698f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
16992999313aSBarry Smith   so this routine is rarely needed.
17002999313aSBarry Smith 
1701f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1702420bcc1bSBarry Smith   decreased by one when this is called.
17032999313aSBarry Smith 
170442747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17052999313aSBarry Smith @*/
1706d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1707d71ae5a4SJacob Faibussowitsch {
17082999313aSBarry Smith   PetscFunctionBegin;
17090700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17100700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17112999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17129566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17139566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17142999313aSBarry Smith   snes->ksp = ksp;
17153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17162999313aSBarry Smith }
17172999313aSBarry Smith 
171852baeb72SSatish Balay /*@
1719dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
17209b94acceSBarry Smith 
1721d083f849SBarry Smith   Collective
1722c7afd0dbSLois Curfman McInnes 
1723f6dfbefdSBarry Smith   Input Parameter:
1724906ed7ccSBarry Smith . comm - MPI communicator
17259b94acceSBarry Smith 
17269b94acceSBarry Smith   Output Parameter:
172720f4b53cSBarry Smith . outsnes - the new `SNES` context
17289b94acceSBarry Smith 
1729c7afd0dbSLois Curfman McInnes   Options Database Keys:
1730dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1731dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1732dc4c0fb0SBarry Smith                       as set by `SNESSetJacobian()`
1733dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1734c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1735c1f60f51SBarry Smith 
173636851e7fSLois Curfman McInnes   Level: beginner
173736851e7fSLois Curfman McInnes 
173895452b02SPatrick Sanan   Developer Notes:
1739f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1740efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1741f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1742f6dfbefdSBarry Smith   in `SNESView()`.
1743efd4aadfSBarry Smith 
1744f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1745f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1746f6dfbefdSBarry Smith 
1747dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1748efd4aadfSBarry Smith 
1749e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
17509b94acceSBarry Smith @*/
1751d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1752d71ae5a4SJacob Faibussowitsch {
17539b94acceSBarry Smith   SNES       snes;
1754fa9f3622SBarry Smith   SNESKSPEW *kctx;
175537fcc0dbSBarry Smith 
17563a40ed3dSBarry Smith   PetscFunctionBegin;
17574f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
17580298fd71SBarry Smith   *outsnes = NULL;
17599566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17608ba1e511SMatthew Knepley 
17619566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17627adad957SLisandro Dalcin 
17638d359177SBarry Smith   snes->ops->converged       = SNESConvergedDefault;
17642c155ee1SBarry Smith   snes->usesksp              = PETSC_TRUE;
176588976e71SPeter Brune   snes->tolerancesset        = PETSC_FALSE;
17669b94acceSBarry Smith   snes->max_its              = 50;
17679750a799SBarry Smith   snes->max_funcs            = 10000;
17689b94acceSBarry Smith   snes->norm                 = 0.0;
1769c1e67a49SFande Kong   snes->xnorm                = 0.0;
1770c1e67a49SFande Kong   snes->ynorm                = 0.0;
1771365a6726SPeter Brune   snes->normschedule         = SNES_NORM_ALWAYS;
17726c67d002SPeter Brune   snes->functype             = SNES_FUNCTION_DEFAULT;
17738ca48ce9SPierre Jolivet   snes->rtol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
1774b4874afaSBarry Smith   snes->ttol                 = 0.0;
17758ca48ce9SPierre Jolivet   snes->abstol               = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50;
17768ca48ce9SPierre Jolivet   snes->stol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
17778ca48ce9SPierre Jolivet   snes->deltatol             = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12;
1778e37c518bSBarry Smith   snes->divtol               = 1.e4;
1779e37c518bSBarry Smith   snes->rnorm0               = 0;
17809b94acceSBarry Smith   snes->nfuncs               = 0;
178150ffb88aSMatthew Knepley   snes->numFailures          = 0;
178250ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17837a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1784e35cf81dSBarry Smith   snes->lagjacobian          = 1;
178537ec4e1aSPeter Brune   snes->jac_iter             = 0;
178637ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1787a8054027SBarry Smith   snes->lagpreconditioner    = 1;
178837ec4e1aSPeter Brune   snes->pre_iter             = 0;
178937ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1790639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1791c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17929e5d0892SLisandro Dalcin   snes->data                 = NULL;
17934dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1794186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17956f24a144SLois Curfman McInnes   snes->nwork                = 0;
17969e5d0892SLisandro Dalcin   snes->work                 = NULL;
179758c9b817SLisandro Dalcin   snes->nvwork               = 0;
17989e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1799758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1800758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18010298fd71SBarry Smith   snes->conv_hist            = NULL;
18020298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1803758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1804971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1805e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1806184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1807efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1808b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1809c40d0f55SPeter Brune 
1810d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1811d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1812d8f46077SPeter Brune   snes->mf_version  = 1;
1813d8f46077SPeter Brune 
18143d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18153d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18163d4c4710SBarry Smith 
1817349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
181876bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1819349187a7SBarry Smith 
18204fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18214fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
18224fc747eaSLawrence Mitchell 
18239b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18244dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1825f5af7f23SKarl Rupp 
18269b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
18279b94acceSBarry Smith   kctx->version     = 2;
18280f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
18299b94acceSBarry Smith                              this was too large for some test cases */
183075567043SBarry Smith   kctx->rtol_last   = 0.0;
18310f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
18329b94acceSBarry Smith   kctx->gamma       = 1.0;
18330f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
183471f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
18350f0abf79SStefano Zampini   kctx->threshold   = 0.1;
183675567043SBarry Smith   kctx->lresid_last = 0.0;
183775567043SBarry Smith   kctx->norm_last   = 0.0;
18389b94acceSBarry Smith 
18390f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
18400f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
18410f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
18420f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
18430f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
18440f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
18450f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
18460f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
18470f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
18480f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
18490f0abf79SStefano Zampini 
18509b94acceSBarry Smith   *outsnes = snes;
18513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18529b94acceSBarry Smith }
18539b94acceSBarry Smith 
18549b94acceSBarry Smith /*@C
18559b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1856f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
18579b94acceSBarry Smith   equations.
18589b94acceSBarry Smith 
1859c3339decSBarry Smith   Logically Collective
1860fee21e36SBarry Smith 
1861c7afd0dbSLois Curfman McInnes   Input Parameters:
1862f6dfbefdSBarry Smith + snes - the `SNES` context
1863dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
18648434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1865c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1866dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
18679b94acceSBarry Smith 
186836851e7fSLois Curfman McInnes   Level: beginner
186936851e7fSLois Curfman McInnes 
18708434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
18719b94acceSBarry Smith @*/
18728434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1873d71ae5a4SJacob Faibussowitsch {
18746cab3a1bSJed Brown   DM dm;
18756cab3a1bSJed Brown 
18763a40ed3dSBarry Smith   PetscFunctionBegin;
18770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1878d2a683ecSLisandro Dalcin   if (r) {
1879d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1880d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18819566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18829566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
188385385478SLisandro Dalcin     snes->vec_func = r;
1884d2a683ecSLisandro Dalcin   }
18859566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18869566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
188748a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18899b94acceSBarry Smith }
18909b94acceSBarry Smith 
1891e4ed7901SPeter Brune /*@C
18920b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1893e4ed7901SPeter Brune 
1894c3339decSBarry Smith   Logically Collective
1895e4ed7901SPeter Brune 
1896e4ed7901SPeter Brune   Input Parameters:
1897f6dfbefdSBarry Smith + snes - the `SNES` context
1898e4ed7901SPeter Brune - f    - vector to store function value
1899e4ed7901SPeter Brune 
1900dc4c0fb0SBarry Smith   Level: developer
1901dc4c0fb0SBarry Smith 
1902e4ed7901SPeter Brune   Notes:
1903e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1904e4ed7901SPeter Brune 
1905f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1906e4ed7901SPeter Brune 
19071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1908e4ed7901SPeter Brune @*/
1909d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1910d71ae5a4SJacob Faibussowitsch {
1911e4ed7901SPeter Brune   Vec vec_func;
1912e4ed7901SPeter Brune 
1913e4ed7901SPeter Brune   PetscFunctionBegin;
1914e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1915e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1916e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1917efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1918902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19193ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1920902f982fSPeter Brune   }
19219566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19229566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1923f5af7f23SKarl Rupp 
1924217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1926e4ed7901SPeter Brune }
1927e4ed7901SPeter Brune 
1928534ebe21SPeter Brune /*@
1929f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1930f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1931534ebe21SPeter Brune 
1932c3339decSBarry Smith   Logically Collective
1933534ebe21SPeter Brune 
1934534ebe21SPeter Brune   Input Parameters:
1935f6dfbefdSBarry Smith + snes         - the `SNES` context
1936365a6726SPeter Brune - normschedule - the frequency of norm computation
1937534ebe21SPeter Brune 
1938517f1916SMatthew G. Knepley   Options Database Key:
193967b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1940517f1916SMatthew G. Knepley 
1941dc4c0fb0SBarry Smith   Level: advanced
1942dc4c0fb0SBarry Smith 
1943534ebe21SPeter Brune   Notes:
1944f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1945534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
1946534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1947f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1948534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
1949534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
1950534ebe21SPeter Brune   their solution.
1951534ebe21SPeter Brune 
1952e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
1953534ebe21SPeter Brune @*/
1954d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1955d71ae5a4SJacob Faibussowitsch {
1956534ebe21SPeter Brune   PetscFunctionBegin;
1957534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1958365a6726SPeter Brune   snes->normschedule = normschedule;
19593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1960534ebe21SPeter Brune }
1961534ebe21SPeter Brune 
1962534ebe21SPeter Brune /*@
1963f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1964f6dfbefdSBarry Smith   of the `SNES` method.
1965534ebe21SPeter Brune 
1966c3339decSBarry Smith   Logically Collective
1967534ebe21SPeter Brune 
1968534ebe21SPeter Brune   Input Parameters:
1969f6dfbefdSBarry Smith + snes         - the `SNES` context
1970365a6726SPeter Brune - normschedule - the type of the norm used
1971534ebe21SPeter Brune 
1972534ebe21SPeter Brune   Level: advanced
1973534ebe21SPeter Brune 
19741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1975534ebe21SPeter Brune @*/
1976d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1977d71ae5a4SJacob Faibussowitsch {
1978534ebe21SPeter Brune   PetscFunctionBegin;
1979534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1980365a6726SPeter Brune   *normschedule = snes->normschedule;
19813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1982534ebe21SPeter Brune }
1983534ebe21SPeter Brune 
1984c5ce4427SMatthew G. Knepley /*@
1985c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1986c5ce4427SMatthew G. Knepley 
1987c3339decSBarry Smith   Logically Collective
1988c5ce4427SMatthew G. Knepley 
1989c5ce4427SMatthew G. Knepley   Input Parameters:
1990f6dfbefdSBarry Smith + snes - the `SNES` context
1991f6dfbefdSBarry Smith - norm - the value of the norm
1992c5ce4427SMatthew G. Knepley 
1993c5ce4427SMatthew G. Knepley   Level: developer
1994c5ce4427SMatthew G. Knepley 
19951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1996c5ce4427SMatthew G. Knepley @*/
1997d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1998d71ae5a4SJacob Faibussowitsch {
1999c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2000c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2001c5ce4427SMatthew G. Knepley   snes->norm = norm;
20023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2003c5ce4427SMatthew G. Knepley }
2004c5ce4427SMatthew G. Knepley 
2005c5ce4427SMatthew G. Knepley /*@
2006c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2007c5ce4427SMatthew G. Knepley 
2008c5ce4427SMatthew G. Knepley   Not Collective
2009c5ce4427SMatthew G. Knepley 
2010c5ce4427SMatthew G. Knepley   Input Parameter:
2011f6dfbefdSBarry Smith . snes - the `SNES` context
2012c5ce4427SMatthew G. Knepley 
2013c5ce4427SMatthew G. Knepley   Output Parameter:
2014c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2015c5ce4427SMatthew G. Knepley 
2016c5ce4427SMatthew G. Knepley   Level: developer
2017c5ce4427SMatthew G. Knepley 
20181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2019c5ce4427SMatthew G. Knepley @*/
2020d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2021d71ae5a4SJacob Faibussowitsch {
2022c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2023c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20244f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2025c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2027c5ce4427SMatthew G. Knepley }
2028c5ce4427SMatthew G. Knepley 
2029c1e67a49SFande Kong /*@
2030f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2031c1e67a49SFande Kong 
2032c1e67a49SFande Kong   Not Collective
2033c1e67a49SFande Kong 
2034c1e67a49SFande Kong   Input Parameter:
2035f6dfbefdSBarry Smith . snes - the `SNES` context
2036c1e67a49SFande Kong 
2037c1e67a49SFande Kong   Output Parameter:
2038c1e67a49SFande Kong . ynorm - the last computed update norm
2039c1e67a49SFande Kong 
2040c1e67a49SFande Kong   Level: developer
2041c1e67a49SFande Kong 
2042f6dfbefdSBarry Smith   Note:
2043f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2044f6dfbefdSBarry Smith 
20451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2046c1e67a49SFande Kong @*/
2047d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2048d71ae5a4SJacob Faibussowitsch {
2049c1e67a49SFande Kong   PetscFunctionBegin;
2050c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20514f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2052c1e67a49SFande Kong   *ynorm = snes->ynorm;
20533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2054c1e67a49SFande Kong }
2055c1e67a49SFande Kong 
2056c1e67a49SFande Kong /*@
20574591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2058c1e67a49SFande Kong 
2059c1e67a49SFande Kong   Not Collective
2060c1e67a49SFande Kong 
2061c1e67a49SFande Kong   Input Parameter:
2062f6dfbefdSBarry Smith . snes - the `SNES` context
2063c1e67a49SFande Kong 
2064c1e67a49SFande Kong   Output Parameter:
2065c1e67a49SFande Kong . xnorm - the last computed solution norm
2066c1e67a49SFande Kong 
2067c1e67a49SFande Kong   Level: developer
2068c1e67a49SFande Kong 
20691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2070c1e67a49SFande Kong @*/
2071d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2072d71ae5a4SJacob Faibussowitsch {
2073c1e67a49SFande Kong   PetscFunctionBegin;
2074c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20754f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2076c1e67a49SFande Kong   *xnorm = snes->xnorm;
20773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2078c1e67a49SFande Kong }
2079c1e67a49SFande Kong 
208047073ea2SPeter Brune /*@C
2081f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2082f6dfbefdSBarry Smith   of the `SNES` method.
208347073ea2SPeter Brune 
2084c3339decSBarry Smith   Logically Collective
208547073ea2SPeter Brune 
208647073ea2SPeter Brune   Input Parameters:
2087f6dfbefdSBarry Smith + snes - the `SNES` context
2088f6dfbefdSBarry Smith - type - the function type
208947073ea2SPeter Brune 
209047073ea2SPeter Brune   Level: developer
209147073ea2SPeter Brune 
2092420bcc1bSBarry Smith   Values of the function type\:
2093f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2094f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2095f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2096f6dfbefdSBarry Smith 
2097420bcc1bSBarry Smith   Note:
2098f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2099f6dfbefdSBarry Smith 
21001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
210147073ea2SPeter Brune @*/
2102d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2103d71ae5a4SJacob Faibussowitsch {
210447073ea2SPeter Brune   PetscFunctionBegin;
210547073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
210647073ea2SPeter Brune   snes->functype = type;
21073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210847073ea2SPeter Brune }
210947073ea2SPeter Brune 
211047073ea2SPeter Brune /*@C
2111f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
211247073ea2SPeter Brune   of the SNES method.
211347073ea2SPeter Brune 
2114c3339decSBarry Smith   Logically Collective
211547073ea2SPeter Brune 
211647073ea2SPeter Brune   Input Parameters:
2117f6dfbefdSBarry Smith + snes - the `SNES` context
2118f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
211947073ea2SPeter Brune 
212047073ea2SPeter Brune   Level: advanced
212147073ea2SPeter Brune 
21221cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
212347073ea2SPeter Brune @*/
2124d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2125d71ae5a4SJacob Faibussowitsch {
212647073ea2SPeter Brune   PetscFunctionBegin;
212747073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
212847073ea2SPeter Brune   *type = snes->functype;
21293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2130534ebe21SPeter Brune }
2131534ebe21SPeter Brune 
2132c79ef259SPeter Brune /*@C
2133be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2134c79ef259SPeter Brune   use with composed nonlinear solvers.
2135c79ef259SPeter Brune 
2136c79ef259SPeter Brune   Input Parameters:
21379bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
21388434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
2139c79ef259SPeter Brune - ctx  - [optional] user-defined context for private data for the
2140dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2141c79ef259SPeter Brune 
2142dc4c0fb0SBarry Smith   Level: intermediate
2143dc4c0fb0SBarry Smith 
2144f6dfbefdSBarry Smith   Note:
2145f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2146f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2147c79ef259SPeter Brune 
21488434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2149c79ef259SPeter Brune @*/
21508434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2151d71ae5a4SJacob Faibussowitsch {
21526cab3a1bSJed Brown   DM dm;
21536cab3a1bSJed Brown 
2154646217ecSPeter Brune   PetscFunctionBegin;
21556cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21579566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2159646217ecSPeter Brune }
2160646217ecSPeter Brune 
2161bbc1464cSBarry Smith /*
2162bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2163bbc1464cSBarry Smith    changed during the KSPSolve()
2164bbc1464cSBarry Smith */
2165d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2166d71ae5a4SJacob Faibussowitsch {
2167bbc1464cSBarry Smith   DM     dm;
2168bbc1464cSBarry Smith   DMSNES sdm;
2169bbc1464cSBarry Smith 
2170bbc1464cSBarry Smith   PetscFunctionBegin;
21719566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21729566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2173bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2174bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2175792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21769566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21770df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2178ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2179792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21809566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2181bbc1464cSBarry Smith   } else {
2182792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21839566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2184bbc1464cSBarry Smith   }
21853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2186bbc1464cSBarry Smith }
2187bbc1464cSBarry Smith 
2188d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2189d71ae5a4SJacob Faibussowitsch {
2190e03ab78fSPeter Brune   DM     dm;
2191942e3340SBarry Smith   DMSNES sdm;
21926cab3a1bSJed Brown 
21938b0a5094SBarry Smith   PetscFunctionBegin;
21949566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21959566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
21968b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2197bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2198792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21999566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2200792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22019566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2202bbc1464cSBarry Smith   } else {
2203792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22049566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2205bbc1464cSBarry Smith   }
22063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22078b0a5094SBarry Smith }
22088b0a5094SBarry Smith 
2209d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2210d71ae5a4SJacob Faibussowitsch {
22118b0a5094SBarry Smith   PetscFunctionBegin;
2212e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2213bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22149566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22159566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22178b0a5094SBarry Smith }
22188b0a5094SBarry Smith 
22198b0a5094SBarry Smith /*@C
22201d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22218b0a5094SBarry Smith 
2222c3339decSBarry Smith   Logically Collective
22238b0a5094SBarry Smith 
22248b0a5094SBarry Smith   Input Parameters:
2225f6dfbefdSBarry Smith + snes - the `SNES` context
2226dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
22278434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
22286b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2229dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
22308434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2231dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2232dc4c0fb0SBarry Smith 
2233dc4c0fb0SBarry Smith   Level: intermediate
22348b0a5094SBarry Smith 
22358b0a5094SBarry Smith   Notes:
22366b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2237f450aa47SBarry 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.
2238f450aa47SBarry Smith 
2239f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22408b0a5094SBarry Smith 
22411d27aa22SBarry 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}$.
22421d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
22438b0a5094SBarry Smith 
2244dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22458b0a5094SBarry Smith 
22460d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22471d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
22488b0a5094SBarry Smith 
22498b0a5094SBarry 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
22501d27aa22SBarry 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
22511d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
22528b0a5094SBarry Smith 
22531d27aa22SBarry 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
2254f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
22556b7fb656SBarry Smith 
225615229ffcSPierre 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.
22576b7fb656SBarry Smith 
2258dc4c0fb0SBarry 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
22596b7fb656SBarry 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
2260f6dfbefdSBarry 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`.
2261aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2262bbc1464cSBarry Smith 
22639bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
22648434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
22658b0a5094SBarry Smith @*/
22668434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2267d71ae5a4SJacob Faibussowitsch {
2268e03ab78fSPeter Brune   DM dm;
2269e03ab78fSPeter Brune 
22708b0a5094SBarry Smith   PetscFunctionBegin;
22718b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22729566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22739566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22749566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22759566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22769566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22788b0a5094SBarry Smith }
22798b0a5094SBarry Smith 
22807971a8bfSPeter Brune /*@C
22817971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
22827971a8bfSPeter Brune 
2283f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
22847971a8bfSPeter Brune 
22857971a8bfSPeter Brune   Input Parameter:
2286f6dfbefdSBarry Smith . snes - the `SNES` context
22877971a8bfSPeter Brune 
2288d8d19677SJose E. Roman   Output Parameters:
2289dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
22908434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2291dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2292dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
22938434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2294dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
22957971a8bfSPeter Brune 
22967971a8bfSPeter Brune   Level: advanced
22977971a8bfSPeter Brune 
22988434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
22997971a8bfSPeter Brune @*/
23008434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2301d71ae5a4SJacob Faibussowitsch {
23027971a8bfSPeter Brune   DM dm;
23037971a8bfSPeter Brune 
23047971a8bfSPeter Brune   PetscFunctionBegin;
23057971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23069566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23079566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23089566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23099566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23117971a8bfSPeter Brune }
23127971a8bfSPeter Brune 
2313d25893d9SBarry Smith /*@C
2314dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2315d25893d9SBarry Smith 
2316c3339decSBarry Smith   Logically Collective
2317d25893d9SBarry Smith 
2318d25893d9SBarry Smith   Input Parameters:
2319f6dfbefdSBarry Smith + snes - the `SNES` context
23208434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2321d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2322dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2323d25893d9SBarry Smith 
2324d25893d9SBarry Smith   Level: intermediate
2325d25893d9SBarry Smith 
23268434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2327d25893d9SBarry Smith @*/
23288434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2329d71ae5a4SJacob Faibussowitsch {
2330d25893d9SBarry Smith   PetscFunctionBegin;
2331d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2332d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2333d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2335d25893d9SBarry Smith }
2336d25893d9SBarry Smith 
23371096aae1SMatthew Knepley /*@C
2338dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2339dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
23401096aae1SMatthew Knepley 
2341c3339decSBarry Smith   Logically Collective
23421096aae1SMatthew Knepley 
23431096aae1SMatthew Knepley   Input Parameter:
2344f6dfbefdSBarry Smith . snes - the `SNES` context
23451096aae1SMatthew Knepley 
23461096aae1SMatthew Knepley   Output Parameter:
2347dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
23481096aae1SMatthew Knepley 
23491096aae1SMatthew Knepley   Level: intermediate
23501096aae1SMatthew Knepley 
23511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23521096aae1SMatthew Knepley @*/
2353d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2354d71ae5a4SJacob Faibussowitsch {
23551096aae1SMatthew Knepley   PetscFunctionBegin;
23560700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23574f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
235885385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23601096aae1SMatthew Knepley }
23611096aae1SMatthew Knepley 
23629b94acceSBarry Smith /*@
2363f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23649b94acceSBarry Smith 
2365c3339decSBarry Smith   Collective
2366c7afd0dbSLois Curfman McInnes 
23679b94acceSBarry Smith   Input Parameters:
2368f6dfbefdSBarry Smith + snes - the `SNES` context
2369c7afd0dbSLois Curfman McInnes - x    - input vector
23709b94acceSBarry Smith 
23719b94acceSBarry Smith   Output Parameter:
2372f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
23739b94acceSBarry Smith 
2374dc4c0fb0SBarry Smith   Level: developer
2375dc4c0fb0SBarry Smith 
237600677de2SStefano Zampini   Notes:
2377f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2378bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
237936851e7fSLois Curfman McInnes 
238000677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
238100677de2SStefano Zampini 
23821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
23839b94acceSBarry Smith @*/
2384d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2385d71ae5a4SJacob Faibussowitsch {
23866cab3a1bSJed Brown   DM     dm;
2387942e3340SBarry Smith   DMSNES sdm;
23889b94acceSBarry Smith 
23893a40ed3dSBarry Smith   PetscFunctionBegin;
23900700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23910700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
23920700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2393c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2394c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2395e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2396184914b5SBarry Smith 
23979566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23989566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
23990fdf79fbSJacob 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().");
240032f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
240148a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24029566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24038ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24048ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2405800f99ffSJeremy L Thompson     {
2406800f99ffSJeremy L Thompson       void           *ctx;
24078434afd1SBarry Smith       SNESFunctionFn *computefunction;
2408800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2409800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2410800f99ffSJeremy L Thompson     }
24119566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
241248a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24130fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24149566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24150fdf79fbSJacob Faibussowitsch   }
24161baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2417ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2418422a814eSBarry Smith   /*
2419422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2420422a814eSBarry Smith      propagate the value to all processes
2421422a814eSBarry Smith   */
24221baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24249b94acceSBarry Smith }
24259b94acceSBarry Smith 
2426c79ef259SPeter Brune /*@
2427f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2428bbc1464cSBarry Smith 
2429c3339decSBarry Smith   Collective
2430bbc1464cSBarry Smith 
2431bbc1464cSBarry Smith   Input Parameters:
2432f6dfbefdSBarry Smith + snes - the `SNES` context
2433bbc1464cSBarry Smith - x    - input vector
2434bbc1464cSBarry Smith 
2435bbc1464cSBarry Smith   Output Parameter:
2436f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2437bbc1464cSBarry Smith 
2438dc4c0fb0SBarry Smith   Level: developer
2439dc4c0fb0SBarry Smith 
2440bbc1464cSBarry Smith   Notes:
2441420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2442bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2443bbc1464cSBarry Smith 
2444dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2445f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2446dd8e379bSPierre 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.
2447bbc1464cSBarry Smith 
24481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2449bbc1464cSBarry Smith @*/
2450d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2451d71ae5a4SJacob Faibussowitsch {
2452bbc1464cSBarry Smith   DM     dm;
2453bbc1464cSBarry Smith   DMSNES sdm;
2454bbc1464cSBarry Smith 
2455bbc1464cSBarry Smith   PetscFunctionBegin;
2456bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2457bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2458bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2459bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2460bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2461e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2462bbc1464cSBarry Smith 
24639566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24649566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24669566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2467bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2468bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2469792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24709566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2472bbc1464cSBarry Smith   snes->nfuncs++;
2473bbc1464cSBarry Smith   /*
2474bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2475bbc1464cSBarry Smith      propagate the value to all processes
2476bbc1464cSBarry Smith   */
24771baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2479bbc1464cSBarry Smith }
2480bbc1464cSBarry Smith 
2481bbc1464cSBarry Smith /*@
2482f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2483c79ef259SPeter Brune 
2484c3339decSBarry Smith   Collective
2485c79ef259SPeter Brune 
2486c79ef259SPeter Brune   Input Parameters:
2487f6dfbefdSBarry Smith + snes - the `SNES` context
2488c79ef259SPeter Brune . x    - input vector
2489c79ef259SPeter Brune - b    - rhs vector
2490c79ef259SPeter Brune 
2491c79ef259SPeter Brune   Output Parameter:
2492c79ef259SPeter Brune . x - new solution vector
2493c79ef259SPeter Brune 
2494dc4c0fb0SBarry Smith   Level: developer
2495dc4c0fb0SBarry Smith 
2496f6dfbefdSBarry Smith   Note:
2497f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2498c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2499c79ef259SPeter Brune   themselves.
2500c79ef259SPeter Brune 
25018434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2502c79ef259SPeter Brune @*/
2503d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2504d71ae5a4SJacob Faibussowitsch {
25056cab3a1bSJed Brown   DM     dm;
2506942e3340SBarry Smith   DMSNES sdm;
2507646217ecSPeter Brune 
2508646217ecSPeter Brune   PetscFunctionBegin;
2509646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2510064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2511064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2512064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2513064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2514e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25169566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25179566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25180fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25199566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2520792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25219566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2524646217ecSPeter Brune }
2525646217ecSPeter Brune 
2526494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2527494a190aSStefano Zampini {
2528494a190aSStefano Zampini   Vec          X;
2529494a190aSStefano Zampini   PetscScalar *g;
2530494a190aSStefano Zampini   PetscReal    f, f2;
2531494a190aSStefano Zampini   PetscInt     low, high, N, i;
2532494a190aSStefano Zampini   PetscBool    flg;
2533494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2534494a190aSStefano Zampini 
2535494a190aSStefano Zampini   PetscFunctionBegin;
2536494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2537494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2538494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2539494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2540494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2541494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2542494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2543494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2544494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2545494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2546494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2547494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2548494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2549494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2550494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2551494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2552494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2553494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2554494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2555494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2556494a190aSStefano Zampini   }
2557494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2558494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2559494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2560494a190aSStefano Zampini }
2561494a190aSStefano Zampini 
2562494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2563494a190aSStefano Zampini {
2564494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2565494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2566494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2567494a190aSStefano Zampini   PetscScalar       dot;
2568494a190aSStefano Zampini   MPI_Comm          comm;
2569494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2570494a190aSStefano Zampini   PetscViewerFormat format;
2571494a190aSStefano Zampini   PetscInt          tabs;
2572494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
25738434afd1SBarry Smith   SNESObjectiveFn  *objective;
2574494a190aSStefano Zampini 
2575494a190aSStefano Zampini   PetscFunctionBegin;
2576494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2577494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2578494a190aSStefano Zampini 
2579494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2580494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2581494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2582494a190aSStefano Zampini   PetscOptionsEnd();
2583494a190aSStefano Zampini   if (!test) {
2584494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2585494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2586494a190aSStefano Zampini   }
2587494a190aSStefano Zampini 
2588494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2589494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2590494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2591494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2592494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2593494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2594494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2595494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2596494a190aSStefano Zampini   }
2597494a190aSStefano Zampini   if (!directionsprinted) {
2598494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2599494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2600494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2601494a190aSStefano Zampini   }
2602494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2603494a190aSStefano Zampini 
2604494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2605494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2606494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2607494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2608494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2609494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2610494a190aSStefano Zampini 
2611494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2612494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2613494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2614494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2615494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2616494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2617494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2618494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2619494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2620494a190aSStefano 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))));
2621494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2622494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2623494a190aSStefano Zampini 
2624494a190aSStefano Zampini   if (complete_print) {
2625494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2626494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2627494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2628494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2629494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2630494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2631494a190aSStefano Zampini   }
2632494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2633494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2634494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2635494a190aSStefano Zampini 
2636494a190aSStefano Zampini   if (complete_print) {
2637494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2638494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2639494a190aSStefano Zampini   }
2640494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2641494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2642494a190aSStefano Zampini }
2643494a190aSStefano Zampini 
2644d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2645d71ae5a4SJacob Faibussowitsch {
264612837594SBarry Smith   Mat               A, B, C, D, jacobian;
26474df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2648e885f1abSBarry Smith   PetscReal         nrm, gnorm;
264981e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
26500e276705SLisandro Dalcin   MatType           mattype;
2651e885f1abSBarry Smith   PetscInt          m, n, M, N;
2652e885f1abSBarry Smith   void             *functx;
26532cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
26543325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2655e885f1abSBarry Smith   MPI_Comm          comm;
2656e885f1abSBarry Smith   PetscInt          tabs;
265712837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
26583325ff46SBarry Smith   PetscViewerFormat format;
2659e885f1abSBarry Smith 
2660e885f1abSBarry Smith   PetscFunctionBegin;
2661d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
26629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
26639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
26649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
26654ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
26669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
26679566063dSJacob 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));
2668d0609cedSBarry Smith   PetscOptionsEnd();
26693ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2670e885f1abSBarry Smith 
26719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
26729566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
26739566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
26749566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
26759566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
267612837594SBarry Smith   if (!complete_print && !directionsprinted) {
26779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
26789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
267912837594SBarry Smith   }
268012837594SBarry Smith   if (!directionsprinted) {
26819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
26829566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
268312837594SBarry Smith     directionsprinted = PETSC_TRUE;
2684e885f1abSBarry Smith   }
26851baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2686e885f1abSBarry Smith 
26879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
268812837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
268912837594SBarry Smith   else jacobian = snes->jacobian_pre;
269012837594SBarry Smith 
26914df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
26924df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
26939566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
26944df93895SStefano Zampini 
2695a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
26969566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
26979566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
26989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
269912837594SBarry Smith   while (jacobian) {
27002cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
27012cd624f9SStefano Zampini 
27022cd624f9SStefano Zampini     if (istranspose) {
27039566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
27042cd624f9SStefano Zampini       Jsave    = jacobian;
27052cd624f9SStefano Zampini       jacobian = JT;
27062cd624f9SStefano Zampini     }
27079566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
270812837594SBarry Smith     if (flg) {
270912837594SBarry Smith       A = jacobian;
27109566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
271112837594SBarry Smith     } else {
27129566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
271312837594SBarry Smith     }
2714e885f1abSBarry Smith 
27159566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
27169566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
27179566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
27189566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
27199566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
27209566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
27219566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
27229566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
27239566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2724e885f1abSBarry Smith 
27259566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
27269566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
272712837594SBarry Smith 
27289566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
27299566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
27309566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
27319566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
27329566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
273312837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
27349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
273512837594SBarry Smith 
2736e885f1abSBarry Smith     if (complete_print) {
27379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
27389566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
27399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
27409566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2741e885f1abSBarry Smith     }
2742e885f1abSBarry Smith 
2743df10fb39SFande Kong     if (threshold_print || complete_print) {
2744e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2745e885f1abSBarry Smith       PetscScalar       *cvals;
2746e885f1abSBarry Smith       const PetscInt    *bcols;
2747e885f1abSBarry Smith       const PetscScalar *bvals;
2748e885f1abSBarry Smith 
27499566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
27509566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
27519566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
27529566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
27539566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
27549566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
27550e276705SLisandro Dalcin 
27569566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
27579566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2758e885f1abSBarry Smith 
2759e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
27609566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
27619566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2762e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
276323a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2764e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2765e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2766e885f1abSBarry Smith             cncols += 1;
2767e885f1abSBarry Smith           }
2768e885f1abSBarry Smith         }
276948a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
27709566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
27719566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2772e885f1abSBarry Smith       }
27739566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
27749566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
27759566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
27769566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
27779566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2778e885f1abSBarry Smith     }
27799566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
27809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
27819566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
27822cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
278312837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
278412837594SBarry Smith       jacobian = snes->jacobian_pre;
27859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
27869371c9d4SSatish Balay     } else jacobian = NULL;
278712837594SBarry Smith   }
27889566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
27891baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2790cd791dc2SBarry Smith   if (mviewer) PetscCall(PetscOptionsRestoreViewer(&mviewer));
27919566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
27923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2793e885f1abSBarry Smith }
2794e885f1abSBarry Smith 
279562fef451SLois Curfman McInnes /*@
2796f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
279762fef451SLois Curfman McInnes 
2798c3339decSBarry Smith   Collective
2799c7afd0dbSLois Curfman McInnes 
280062fef451SLois Curfman McInnes   Input Parameters:
2801f6dfbefdSBarry Smith + snes - the `SNES` context
2802e4094ef1SJacob Faibussowitsch - X    - input vector
280362fef451SLois Curfman McInnes 
280462fef451SLois Curfman McInnes   Output Parameters:
2805c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2806420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2807fee21e36SBarry Smith 
2808e35cf81dSBarry Smith   Options Database Keys:
280967b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
281067b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2811455a5933SJed 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.
2812455a5933SJed 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
2813693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2814693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2815693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
28164c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
281794d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2818a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2819c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2820dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2821dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2822a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2823a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2824c01495d3SJed Brown 
2825dc4c0fb0SBarry Smith   Level: developer
2826dc4c0fb0SBarry Smith 
2827f6dfbefdSBarry Smith   Note:
282862fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
282962fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
283062fef451SLois Curfman McInnes 
2831420bcc1bSBarry Smith   Developer Note:
2832dc4c0fb0SBarry 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
2833420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2834e885f1abSBarry Smith 
28351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
283662fef451SLois Curfman McInnes @*/
2837d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2838d71ae5a4SJacob Faibussowitsch {
2839ace3abfcSBarry Smith   PetscBool flag;
28406cab3a1bSJed Brown   DM        dm;
2841942e3340SBarry Smith   DMSNES    sdm;
2842e0e3a89bSBarry Smith   KSP       ksp;
28433a40ed3dSBarry Smith 
28443a40ed3dSBarry Smith   PetscFunctionBegin;
28450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
28460700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2847c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2848e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
28499566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
28509566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
28513232da50SPeter Brune 
285201c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2853fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2854fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2855f5af7f23SKarl Rupp 
28569566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2857fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
28589566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
28599566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2860ebd3b9afSBarry Smith     if (flag) {
28619566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28629566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2863ebd3b9afSBarry Smith     }
28643ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
286537ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
286663a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
28679566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2868ebd3b9afSBarry Smith     if (flag) {
28699566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28709566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2871ebd3b9afSBarry Smith     }
28723ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2873e35cf81dSBarry Smith   }
2874efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
28759566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28769566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
28773ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2878d728fb7dSPeter Brune   }
2879e35cf81dSBarry Smith 
28809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
28819566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2882800f99ffSJeremy L Thompson   {
2883800f99ffSJeremy L Thompson     void           *ctx;
28848434afd1SBarry Smith     SNESJacobianFn *J;
2885800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2886800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2887800f99ffSJeremy L Thompson   }
28889566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
28899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
289028d58a37SPierre Jolivet 
289128d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
28929566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2893a8054027SBarry Smith 
2894e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
28959566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
28963b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
28979566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
28989566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
28993b4f5425SBarry Smith     snes->lagpreconditioner = -1;
29003b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
29019566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
29029566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
290337ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
290463a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
29059566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2906d1e9a80fSBarry Smith   } else {
29079566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
29089566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2909a8054027SBarry Smith   }
2910a8054027SBarry Smith 
29114df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
29124df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
29134df93895SStefano Zampini   {
29144df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
29154df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
29164df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
29174df93895SStefano Zampini 
29184df93895SStefano Zampini     snes->vec_sol      = X;
29194df93895SStefano Zampini     snes->jacobian     = A;
29204df93895SStefano Zampini     snes->jacobian_pre = B;
2921494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
29229566063dSJacob Faibussowitsch     PetscCall(SNESTestJacobian(snes));
2923494a190aSStefano Zampini 
29244df93895SStefano Zampini     snes->vec_sol      = xsave;
29254df93895SStefano Zampini     snes->jacobian     = jacobiansave;
29264df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
29274df93895SStefano Zampini   }
29284df93895SStefano Zampini 
2929693365a8SJed Brown   {
2930693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
29319566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
29329566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
29339566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
29349566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2935693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
29360298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2937693365a8SJed Brown       PetscViewer vdraw, vstdout;
29386b3a5b13SJed Brown       PetscBool   flg;
2939693365a8SJed Brown       if (flag_operator) {
29409566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2941693365a8SJed Brown         Bexp = Bexp_mine;
2942693365a8SJed Brown       } else {
2943693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
29449566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
294594ab13aaSBarry Smith         if (flg) Bexp = B;
2946693365a8SJed Brown         else {
2947693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
29489566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2949693365a8SJed Brown           Bexp = Bexp_mine;
2950693365a8SJed Brown         }
2951693365a8SJed Brown       }
29529566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
29539566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
29549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2955693365a8SJed Brown       if (flag_draw || flag_contour) {
29569566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
29579566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29580298fd71SBarry Smith       } else vdraw = NULL;
29599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
29609566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
29619566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
29629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
29639566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
29649566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
29659566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
29669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
29679566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2968693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
29699566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29709566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
29719566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2972693365a8SJed Brown       }
29739566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29749566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29759566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
29769566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2977693365a8SJed Brown     }
2978693365a8SJed Brown   }
29794c30e9fbSJed Brown   {
29806719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
29816719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
29829566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
29839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
29849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
29859566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
29869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
298727b0f280SBarry Smith     if (flag_threshold) {
29889566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
29899566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
299027b0f280SBarry Smith     }
29916719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
29924c30e9fbSJed Brown       Mat             Bfd;
29934c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
2994335efc43SPeter Brune       MatColoring     coloring;
29954c30e9fbSJed Brown       ISColoring      iscoloring;
29964c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
29978434afd1SBarry Smith       SNESFunctionFn *func;
29984c30e9fbSJed Brown       void           *funcctx;
29996719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
30004c30e9fbSJed Brown 
30019566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
30029566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
30039566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
30049566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
30059566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
30069566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
30079566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
30089566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30099566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
30109566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
30114c30e9fbSJed Brown 
30124c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
30139566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
30149566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
30159566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
30169566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
30179566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30189566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
30199566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
30204c30e9fbSJed Brown 
30219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
30224c30e9fbSJed Brown       if (flag_draw || flag_contour) {
30239566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30249566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30250298fd71SBarry Smith       } else vdraw = NULL;
30269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
30279566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
30289566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
30299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
30309566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30319566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
30329566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
30339566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
30349566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
30359566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
30369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
30379566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30384c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
30399566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30409566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
30419566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
30424c30e9fbSJed Brown       }
30439566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30446719d8e4SJed Brown 
30456719d8e4SJed Brown       if (flag_threshold) {
30466719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
30479566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
30489566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
30496719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
30506719d8e4SJed Brown           const PetscScalar *ba, *ca;
30516719d8e4SJed Brown           const PetscInt    *bj, *cj;
30526719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
30536719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
30549566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
30559566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
30565f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
30576719d8e4SJed Brown           for (j = 0; j < bn; j++) {
30586719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
30596719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
30606719d8e4SJed Brown               maxentrycol = bj[j];
30616719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
30626719d8e4SJed Brown             }
30636719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
30646719d8e4SJed Brown               maxdiffcol = bj[j];
30656719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
30666719d8e4SJed Brown             }
30676719d8e4SJed Brown             if (rdiff > maxrdiff) {
30686719d8e4SJed Brown               maxrdiffcol = bj[j];
30696719d8e4SJed Brown               maxrdiff    = rdiff;
30706719d8e4SJed Brown             }
30716719d8e4SJed Brown           }
30726719d8e4SJed Brown           if (maxrdiff > 1) {
307363a3b9bcSJacob 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));
30746719d8e4SJed Brown             for (j = 0; j < bn; j++) {
30756719d8e4SJed Brown               PetscReal rdiff;
30766719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
307748a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
30786719d8e4SJed Brown             }
307963a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
30806719d8e4SJed Brown           }
30819566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
30829566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
30836719d8e4SJed Brown         }
30846719d8e4SJed Brown       }
30859566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30869566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
30874c30e9fbSJed Brown     }
30884c30e9fbSJed Brown   }
30893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30909b94acceSBarry Smith }
30919b94acceSBarry Smith 
30929b94acceSBarry Smith /*@C
30939b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3094044dda88SLois Curfman McInnes   location to store the matrix.
30959b94acceSBarry Smith 
3096c3339decSBarry Smith   Logically Collective
3097c7afd0dbSLois Curfman McInnes 
30989b94acceSBarry Smith   Input Parameters:
3099f6dfbefdSBarry Smith + snes - the `SNES` context
3100e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3101dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
31028434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3103c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3104dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3105dc4c0fb0SBarry Smith 
3106dc4c0fb0SBarry Smith   Level: beginner
31079b94acceSBarry Smith 
31089b94acceSBarry Smith   Notes:
3109dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
311016913363SBarry Smith   each matrix.
311116913363SBarry Smith 
3112dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3113dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3114895c21f2SBarry Smith 
3115dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3116f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3117a8a26c1eSJed Brown 
3118c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3119f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3120c3cc8fd1SJed Brown 
31211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
31228434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
31239b94acceSBarry Smith @*/
31248434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3125d71ae5a4SJacob Faibussowitsch {
31266cab3a1bSJed Brown   DM dm;
31273a7fca6bSBarry Smith 
31283a40ed3dSBarry Smith   PetscFunctionBegin;
31290700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3130e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3131e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3132e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3133e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
31349566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31359566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3136e5d3d808SBarry Smith   if (Amat) {
31379566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
31389566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3139f5af7f23SKarl Rupp 
3140e5d3d808SBarry Smith     snes->jacobian = Amat;
31413a7fca6bSBarry Smith   }
3142e5d3d808SBarry Smith   if (Pmat) {
31439566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
31449566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3145f5af7f23SKarl Rupp 
3146e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
31473a7fca6bSBarry Smith   }
31483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31499b94acceSBarry Smith }
315062fef451SLois Curfman McInnes 
3151c2aafc4cSSatish Balay /*@C
3152b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3153b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3154b4fd4287SBarry Smith 
3155420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3156c7afd0dbSLois Curfman McInnes 
3157b4fd4287SBarry Smith   Input Parameter:
3158b4fd4287SBarry Smith . snes - the nonlinear solver context
3159b4fd4287SBarry Smith 
3160b4fd4287SBarry Smith   Output Parameters:
3161dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3162dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
31638434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3164dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3165fee21e36SBarry Smith 
316636851e7fSLois Curfman McInnes   Level: advanced
316736851e7fSLois Curfman McInnes 
31688434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3169b4fd4287SBarry Smith @*/
31708434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3171d71ae5a4SJacob Faibussowitsch {
31726cab3a1bSJed Brown   DM dm;
31736cab3a1bSJed Brown 
31743a40ed3dSBarry Smith   PetscFunctionBegin;
31750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3176e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3177e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
31789566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3179800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
31803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3181b4fd4287SBarry Smith }
3182b4fd4287SBarry Smith 
3183d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3184d71ae5a4SJacob Faibussowitsch {
318558b371f3SBarry Smith   DM     dm;
318658b371f3SBarry Smith   DMSNES sdm;
318758b371f3SBarry Smith 
318858b371f3SBarry Smith   PetscFunctionBegin;
31899566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31909566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
319158b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
319258b371f3SBarry Smith     DM        dm;
319358b371f3SBarry Smith     PetscBool isdense, ismf;
319458b371f3SBarry Smith 
31959566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31969566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
31979566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
319858b371f3SBarry Smith     if (isdense) {
31999566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
320058b371f3SBarry Smith     } else if (!ismf) {
32019566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
320258b371f3SBarry Smith     }
320358b371f3SBarry Smith   }
32043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
320558b371f3SBarry Smith }
320658b371f3SBarry Smith 
32079b94acceSBarry Smith /*@
32089b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3209272ac6f2SLois Curfman McInnes   of a nonlinear solver.
32109b94acceSBarry Smith 
3211c3339decSBarry Smith   Collective
3212fee21e36SBarry Smith 
32132fe279fdSBarry Smith   Input Parameter:
3214f6dfbefdSBarry Smith . snes - the `SNES` context
3215c7afd0dbSLois Curfman McInnes 
3216dc4c0fb0SBarry Smith   Level: advanced
3217dc4c0fb0SBarry Smith 
3218f6dfbefdSBarry Smith   Note:
3219f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3220f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3221f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3222f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3223f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3224272ac6f2SLois Curfman McInnes 
32251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
32269b94acceSBarry Smith @*/
3227d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3228d71ae5a4SJacob Faibussowitsch {
32296cab3a1bSJed Brown   DM             dm;
3230942e3340SBarry Smith   DMSNES         sdm;
3231c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
32326e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
32339b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
32349b5c1c08SStefano Zampini   Vec            f, fpc;
32359b5c1c08SStefano Zampini   void          *funcctx;
32369b5c1c08SStefano Zampini   void          *jacctx, *appctx;
32379b5c1c08SStefano Zampini   Mat            j, jpre;
32386b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
32396b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
32408434afd1SBarry Smith   SNESFunctionFn *func;
32418434afd1SBarry Smith   SNESJacobianFn *jac;
32423a40ed3dSBarry Smith 
32433a40ed3dSBarry Smith   PetscFunctionBegin;
32440700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
32453ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3246fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
32479b94acceSBarry Smith 
324848a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
324985385478SLisandro Dalcin 
32509566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
325158c9b817SLisandro Dalcin 
32529566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32539566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
32549566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
325558b371f3SBarry Smith 
325648a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3257efd51863SBarry Smith 
325848a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3259b710008aSBarry Smith 
3260d8d34be6SBarry Smith   if (snes->linesearch) {
32619566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
32629566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3263d8d34be6SBarry Smith   }
32649e764e56SPeter Brune 
32659b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3266b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3267172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3268172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3269172a4300SPeter Brune   }
3270d8f46077SPeter Brune 
3271efd4aadfSBarry Smith   if (snes->npc) {
32726e2a1849SPeter Brune     /* copy the DM over */
32739566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32749566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
32756e2a1849SPeter Brune 
32769566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
32779566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
32789566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
32799566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
32809566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
32819566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
32829566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
32839b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
32849566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
32856e2a1849SPeter Brune 
32866e2a1849SPeter Brune     /* copy the function pointers over */
32879566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
32886e2a1849SPeter Brune 
32896e2a1849SPeter Brune     /* default to 1 iteration */
32909566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3291efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
32929566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3293a9936a0cSPeter Brune     } else {
32949566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3295a9936a0cSPeter Brune     }
32969566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
32976e2a1849SPeter Brune 
32986e2a1849SPeter Brune     /* copy the line search context over */
3299d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
33009566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
33019566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
33029566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
33039566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
33049566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
33059566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
33069566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
33076e2a1849SPeter Brune     }
3308d8d34be6SBarry Smith   }
33091baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
33109927e4dfSBarry Smith   if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user));
33116e2a1849SPeter Brune 
331237ec4e1aSPeter Brune   snes->jac_iter = 0;
331337ec4e1aSPeter Brune   snes->pre_iter = 0;
331437ec4e1aSPeter Brune 
3315dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
331658c9b817SLisandro Dalcin 
33179566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
331858b371f3SBarry Smith 
3319b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
33206c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3321d8d34be6SBarry Smith       if (snes->linesearch) {
33229566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
33239566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
33246c67d002SPeter Brune       }
33256c67d002SPeter Brune     }
3326d8d34be6SBarry Smith   }
3327fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
33287aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
33293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33309b94acceSBarry Smith }
33319b94acceSBarry Smith 
333237596af1SLisandro Dalcin /*@
3333f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
333437596af1SLisandro Dalcin 
3335c3339decSBarry Smith   Collective
333637596af1SLisandro Dalcin 
333737596af1SLisandro Dalcin   Input Parameter:
3338f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
333937596af1SLisandro Dalcin 
3340d25893d9SBarry Smith   Level: intermediate
3341d25893d9SBarry Smith 
334295452b02SPatrick Sanan   Notes:
3343f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
334437596af1SLisandro Dalcin 
3345f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3346f6dfbefdSBarry Smith 
33471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
334837596af1SLisandro Dalcin @*/
3349d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3350d71ae5a4SJacob Faibussowitsch {
335137596af1SLisandro Dalcin   PetscFunctionBegin;
335237596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3353d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
33549927e4dfSBarry Smith     PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user));
33550298fd71SBarry Smith     snes->user = NULL;
3356d25893d9SBarry Smith   }
33571baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
33588a23116dSBarry Smith 
3359dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
33601baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
33619e764e56SPeter Brune 
33621baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
33639e764e56SPeter Brune 
33649566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
33659566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
33669566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
33679566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
33689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
33699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
33709566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
33719566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
33729566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3373f5af7f23SKarl Rupp 
337440fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
337540fdac6aSLawrence Mitchell 
337637596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
337737596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
33783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
337937596af1SLisandro Dalcin }
338037596af1SLisandro Dalcin 
338152baeb72SSatish Balay /*@
3382420bcc1bSBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()`
3383c4421ceaSFande Kong 
3384c3339decSBarry Smith   Collective
3385c4421ceaSFande Kong 
3386c4421ceaSFande Kong   Input Parameter:
3387f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3388c4421ceaSFande Kong 
3389c4421ceaSFande Kong   Level: intermediate
3390c4421ceaSFande Kong 
3391420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3392c4421ceaSFande Kong @*/
3393d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3394d71ae5a4SJacob Faibussowitsch {
3395c4421ceaSFande Kong   PetscInt i;
3396c4421ceaSFande Kong 
3397c4421ceaSFande Kong   PetscFunctionBegin;
3398c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3399c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
340048a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3401c4421ceaSFande Kong   }
3402c4421ceaSFande Kong   snes->numberreasonviews = 0;
34033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3404c4421ceaSFande Kong }
3405c4421ceaSFande Kong 
34061fb7b255SJunchao Zhang /*@C
34079b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3408f6dfbefdSBarry Smith   with `SNESCreate()`.
34099b94acceSBarry Smith 
3410c3339decSBarry Smith   Collective
3411c7afd0dbSLois Curfman McInnes 
34129b94acceSBarry Smith   Input Parameter:
3413f6dfbefdSBarry Smith . snes - the `SNES` context
34149b94acceSBarry Smith 
341536851e7fSLois Curfman McInnes   Level: beginner
341636851e7fSLois Curfman McInnes 
34171cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
34189b94acceSBarry Smith @*/
3419d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3420d71ae5a4SJacob Faibussowitsch {
34213a40ed3dSBarry Smith   PetscFunctionBegin;
34223ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3423f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3424f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
34259371c9d4SSatish Balay     *snes = NULL;
34263ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
34279371c9d4SSatish Balay   }
3428d4bb536fSBarry Smith 
3429f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
34309566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
34316b8b9a38SLisandro Dalcin 
3432e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
34339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3434f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
34356d4c513bSLisandro Dalcin 
34369566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
34379566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
34389566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
34399566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
34406b8b9a38SLisandro Dalcin 
34419566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
344248a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
344348a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3444f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3445f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
34469566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
34473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34489b94acceSBarry Smith }
34499b94acceSBarry Smith 
34509b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
34519b94acceSBarry Smith 
3452a8054027SBarry Smith /*@
3453a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3454a8054027SBarry Smith 
3455c3339decSBarry Smith   Logically Collective
3456a8054027SBarry Smith 
3457a8054027SBarry Smith   Input Parameters:
3458f6dfbefdSBarry Smith + snes - the `SNES` context
3459d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
34603b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3461a8054027SBarry Smith 
3462a8054027SBarry Smith   Options Database Keys:
3463420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
34643d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3465420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
34663d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3467a8054027SBarry Smith 
3468dc4c0fb0SBarry Smith   Level: intermediate
3469dc4c0fb0SBarry Smith 
3470420bcc1bSBarry Smith   Notes:
3471a8054027SBarry Smith   The default is 1
3472420bcc1bSBarry Smith 
3473f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3474d8e291bfSBarry Smith 
3475f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3476a8054027SBarry Smith 
34771cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3478f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3479a8054027SBarry Smith @*/
3480d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3481d71ae5a4SJacob Faibussowitsch {
3482a8054027SBarry Smith   PetscFunctionBegin;
34830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34845f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
34855f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3486c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3487a8054027SBarry Smith   snes->lagpreconditioner = lag;
34883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3489a8054027SBarry Smith }
3490a8054027SBarry Smith 
3491efd51863SBarry Smith /*@
3492f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3493efd51863SBarry Smith 
3494c3339decSBarry Smith   Logically Collective
3495efd51863SBarry Smith 
3496efd51863SBarry Smith   Input Parameters:
3497f6dfbefdSBarry Smith + snes  - the `SNES` context
3498efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3499efd51863SBarry Smith 
3500f6dfbefdSBarry Smith   Options Database Key:
350167b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3502efd51863SBarry Smith 
3503efd51863SBarry Smith   Level: intermediate
3504efd51863SBarry Smith 
3505f6dfbefdSBarry Smith   Note:
3506f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3507c0df2a02SJed Brown 
3508420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
3509420bcc1bSBarry Smith           `SNESetDM()`
3510efd51863SBarry Smith @*/
3511d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3512d71ae5a4SJacob Faibussowitsch {
3513efd51863SBarry Smith   PetscFunctionBegin;
3514efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3515efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3516efd51863SBarry Smith   snes->gridsequence = steps;
35173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3518efd51863SBarry Smith }
3519efd51863SBarry Smith 
3520fa19ca70SBarry Smith /*@
3521f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3522fa19ca70SBarry Smith 
3523c3339decSBarry Smith   Logically Collective
3524fa19ca70SBarry Smith 
3525fa19ca70SBarry Smith   Input Parameter:
3526f6dfbefdSBarry Smith . snes - the `SNES` context
3527fa19ca70SBarry Smith 
3528fa19ca70SBarry Smith   Output Parameter:
3529fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3530fa19ca70SBarry Smith 
3531fa19ca70SBarry Smith   Level: intermediate
3532fa19ca70SBarry Smith 
35331cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3534fa19ca70SBarry Smith @*/
3535d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3536d71ae5a4SJacob Faibussowitsch {
3537fa19ca70SBarry Smith   PetscFunctionBegin;
3538fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3539fa19ca70SBarry Smith   *steps = snes->gridsequence;
35403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3541fa19ca70SBarry Smith }
3542fa19ca70SBarry Smith 
3543a8054027SBarry Smith /*@
3544f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3545a8054027SBarry Smith 
35463f9fe445SBarry Smith   Not Collective
3547a8054027SBarry Smith 
3548a8054027SBarry Smith   Input Parameter:
3549f6dfbefdSBarry Smith . snes - the `SNES` context
3550a8054027SBarry Smith 
3551a8054027SBarry Smith   Output Parameter:
3552a8054027SBarry 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
35533b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3554a8054027SBarry Smith 
3555dc4c0fb0SBarry Smith   Level: intermediate
3556dc4c0fb0SBarry Smith 
3557a8054027SBarry Smith   Notes:
3558a8054027SBarry Smith   The default is 1
3559f6dfbefdSBarry Smith 
3560a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3561a8054027SBarry Smith 
35621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3563a8054027SBarry Smith @*/
3564d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3565d71ae5a4SJacob Faibussowitsch {
3566a8054027SBarry Smith   PetscFunctionBegin;
35670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3568a8054027SBarry Smith   *lag = snes->lagpreconditioner;
35693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3570a8054027SBarry Smith }
3571a8054027SBarry Smith 
3572e35cf81dSBarry Smith /*@
3573f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3574e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3575e35cf81dSBarry Smith 
3576c3339decSBarry Smith   Logically Collective
3577e35cf81dSBarry Smith 
3578e35cf81dSBarry Smith   Input Parameters:
3579f6dfbefdSBarry Smith + snes - the `SNES` context
3580e35cf81dSBarry 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
3581fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3582e35cf81dSBarry Smith 
3583e35cf81dSBarry Smith   Options Database Keys:
358479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35853d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
358679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35873d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3588e35cf81dSBarry Smith 
3589dc4c0fb0SBarry Smith   Level: intermediate
3590dc4c0fb0SBarry Smith 
3591e35cf81dSBarry Smith   Notes:
3592e35cf81dSBarry Smith   The default is 1
3593f6dfbefdSBarry Smith 
3594e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3595f6dfbefdSBarry Smith 
3596fe3ffe1eSBarry 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
3597fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3598e35cf81dSBarry Smith 
35991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3600e35cf81dSBarry Smith @*/
3601d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3602d71ae5a4SJacob Faibussowitsch {
3603e35cf81dSBarry Smith   PetscFunctionBegin;
36040700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36055f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36065f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3607c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3608e35cf81dSBarry Smith   snes->lagjacobian = lag;
36093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3610e35cf81dSBarry Smith }
3611e35cf81dSBarry Smith 
3612e35cf81dSBarry Smith /*@
3613f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3614e35cf81dSBarry Smith 
36153f9fe445SBarry Smith   Not Collective
3616e35cf81dSBarry Smith 
3617e35cf81dSBarry Smith   Input Parameter:
3618f6dfbefdSBarry Smith . snes - the `SNES` context
3619e35cf81dSBarry Smith 
3620e35cf81dSBarry Smith   Output Parameter:
3621e35cf81dSBarry 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
3622e35cf81dSBarry Smith          the Jacobian is built etc.
3623e35cf81dSBarry Smith 
3624dc4c0fb0SBarry Smith   Level: intermediate
3625dc4c0fb0SBarry Smith 
3626e35cf81dSBarry Smith   Notes:
3627e35cf81dSBarry Smith   The default is 1
3628f6dfbefdSBarry Smith 
3629f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3630e35cf81dSBarry Smith 
36311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3632e35cf81dSBarry Smith 
3633e35cf81dSBarry Smith @*/
3634d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3635d71ae5a4SJacob Faibussowitsch {
3636e35cf81dSBarry Smith   PetscFunctionBegin;
36370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3638e35cf81dSBarry Smith   *lag = snes->lagjacobian;
36393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3640e35cf81dSBarry Smith }
3641e35cf81dSBarry Smith 
364237ec4e1aSPeter Brune /*@
3643f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
364437ec4e1aSPeter Brune 
3645c3339decSBarry Smith   Logically collective
364637ec4e1aSPeter Brune 
3647d8d19677SJose E. Roman   Input Parameters:
3648f6dfbefdSBarry Smith + snes - the `SNES` context
36499d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
365037ec4e1aSPeter Brune 
365137ec4e1aSPeter Brune   Options Database Keys:
365279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36533d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
365479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36553d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
36563d5a8a6aSBarry Smith 
3657dc4c0fb0SBarry Smith   Level: advanced
3658dc4c0fb0SBarry Smith 
365995452b02SPatrick Sanan   Notes:
3660420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3661f6dfbefdSBarry Smith 
366295452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
366337ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
366437ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
366537ec4e1aSPeter Brune 
366642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
366737ec4e1aSPeter Brune @*/
3668d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3669d71ae5a4SJacob Faibussowitsch {
367037ec4e1aSPeter Brune   PetscFunctionBegin;
367137ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
367237ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
367337ec4e1aSPeter Brune   snes->lagjac_persist = flg;
36743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
367537ec4e1aSPeter Brune }
367637ec4e1aSPeter Brune 
367737ec4e1aSPeter Brune /*@
3678d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
367937ec4e1aSPeter Brune 
3680c3339decSBarry Smith   Logically Collective
368137ec4e1aSPeter Brune 
3682d8d19677SJose E. Roman   Input Parameters:
3683f6dfbefdSBarry Smith + snes - the `SNES` context
36849d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
368537ec4e1aSPeter Brune 
368637ec4e1aSPeter Brune   Options Database Keys:
368779a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36883d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
368979a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36903d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
369137ec4e1aSPeter Brune 
3692dc4c0fb0SBarry Smith   Level: developer
3693dc4c0fb0SBarry Smith 
369495452b02SPatrick Sanan   Notes:
3695420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3696f6dfbefdSBarry Smith 
369795452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
369837ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
369937ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
370037ec4e1aSPeter Brune 
37011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
370237ec4e1aSPeter Brune @*/
3703d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3704d71ae5a4SJacob Faibussowitsch {
370537ec4e1aSPeter Brune   PetscFunctionBegin;
370637ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
370737ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
370837ec4e1aSPeter Brune   snes->lagpre_persist = flg;
37093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
371037ec4e1aSPeter Brune }
371137ec4e1aSPeter Brune 
37129b94acceSBarry Smith /*@
3713f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3714be5caee7SBarry Smith 
3715c3339decSBarry Smith   Logically Collective
3716be5caee7SBarry Smith 
3717be5caee7SBarry Smith   Input Parameters:
3718f6dfbefdSBarry Smith + snes  - the `SNES` context
3719f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3720be5caee7SBarry Smith 
3721f6dfbefdSBarry Smith   Options Database Key:
3722be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3723be5caee7SBarry Smith 
3724dc4c0fb0SBarry Smith   Level: intermediate
3725dc4c0fb0SBarry Smith 
3726f6dfbefdSBarry Smith   Note:
3727f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3728be5caee7SBarry Smith 
37291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3730be5caee7SBarry Smith @*/
3731d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3732d71ae5a4SJacob Faibussowitsch {
3733be5caee7SBarry Smith   PetscFunctionBegin;
3734be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3735be5caee7SBarry Smith   snes->forceiteration = force;
37363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3737be5caee7SBarry Smith }
3738be5caee7SBarry Smith 
373985216dc7SFande Kong /*@
3740f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
374185216dc7SFande Kong 
3742c3339decSBarry Smith   Logically Collective
374385216dc7SFande Kong 
37442fe279fdSBarry Smith   Input Parameter:
3745f6dfbefdSBarry Smith . snes - the `SNES` context
374685216dc7SFande Kong 
374785216dc7SFande Kong   Output Parameter:
3748dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
374985216dc7SFande Kong 
375006dd6b0eSSatish Balay   Level: intermediate
375106dd6b0eSSatish Balay 
37521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
375385216dc7SFande Kong @*/
3754d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3755d71ae5a4SJacob Faibussowitsch {
375685216dc7SFande Kong   PetscFunctionBegin;
375785216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
375885216dc7SFande Kong   *force = snes->forceiteration;
37593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
376085216dc7SFande Kong }
3761be5caee7SBarry Smith 
3762be5caee7SBarry Smith /*@
3763f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
37649b94acceSBarry Smith 
3765c3339decSBarry Smith   Logically Collective
3766c7afd0dbSLois Curfman McInnes 
37679b94acceSBarry Smith   Input Parameters:
3768f6dfbefdSBarry Smith + snes   - the `SNES` context
376970441072SBarry Smith . abstol - absolute convergence tolerance
377033174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
37715358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3772f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
3773f6dfbefdSBarry Smith - maxf   - maximum number of function evaluations (-1 indicates no limit), default 1000
3774fee21e36SBarry Smith 
377533174efeSLois Curfman McInnes   Options Database Keys:
377670441072SBarry Smith + -snes_atol <abstol>    - Sets abstol
3777c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol>      - Sets rtol
3778c7afd0dbSLois Curfman McInnes . -snes_stol <stol>      - Sets stol
3779c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit>   - Sets maxit
3780c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf
37819b94acceSBarry Smith 
378236851e7fSLois Curfman McInnes   Level: intermediate
378336851e7fSLois Curfman McInnes 
378400677de2SStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
37859b94acceSBarry Smith @*/
3786d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3787d71ae5a4SJacob Faibussowitsch {
37883a40ed3dSBarry Smith   PetscFunctionBegin;
37890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3790c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3791c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3792c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3793c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3794c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3795c5eb9154SBarry Smith 
379613bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
37975f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3798ab54825eSJed Brown     snes->abstol = abstol;
3799ab54825eSJed Brown   }
380013bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
38015f80ce2aSJacob 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);
3802ab54825eSJed Brown     snes->rtol = rtol;
3803ab54825eSJed Brown   }
380413bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
38055f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3806c60f73f4SPeter Brune     snes->stol = stol;
3807ab54825eSJed Brown   }
3808ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
380963a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3810ab54825eSJed Brown     snes->max_its = maxit;
3811ab54825eSJed Brown   }
3812ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
381363a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3814ab54825eSJed Brown     snes->max_funcs = maxf;
3815ab54825eSJed Brown   }
381688976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
38173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38189b94acceSBarry Smith }
38199b94acceSBarry Smith 
3820e4d06f11SPatrick Farrell /*@
3821f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3822e4d06f11SPatrick Farrell 
3823c3339decSBarry Smith   Logically Collective
3824e4d06f11SPatrick Farrell 
3825e4d06f11SPatrick Farrell   Input Parameters:
3826f6dfbefdSBarry Smith + snes   - the `SNES` context
3827f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3828e4d06f11SPatrick Farrell 
3829f6dfbefdSBarry Smith   Options Database Key:
3830dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3831e4d06f11SPatrick Farrell 
3832e4d06f11SPatrick Farrell   Level: intermediate
3833e4d06f11SPatrick Farrell 
38341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3835e4d06f11SPatrick Farrell @*/
3836d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3837d71ae5a4SJacob Faibussowitsch {
3838e4d06f11SPatrick Farrell   PetscFunctionBegin;
3839e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3840e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3841e4d06f11SPatrick Farrell 
384213bcc0bdSJacob Faibussowitsch   if (divtol != (PetscReal)PETSC_DEFAULT) {
3843e4d06f11SPatrick Farrell     snes->divtol = divtol;
38449371c9d4SSatish Balay   } else {
3845e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3846e4d06f11SPatrick Farrell   }
38473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3848e4d06f11SPatrick Farrell }
3849e4d06f11SPatrick Farrell 
38509b94acceSBarry Smith /*@
385133174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
385233174efeSLois Curfman McInnes 
3853c7afd0dbSLois Curfman McInnes   Not Collective
3854c7afd0dbSLois Curfman McInnes 
385533174efeSLois Curfman McInnes   Input Parameters:
3856f6dfbefdSBarry Smith + snes  - the `SNES` context
385785385478SLisandro Dalcin . atol  - absolute convergence tolerance
385833174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
385933174efeSLois Curfman McInnes . stol  - convergence tolerance in terms of the norm
386033174efeSLois Curfman McInnes           of the change in the solution between steps
386133174efeSLois Curfman McInnes . maxit - maximum number of iterations
3862c7afd0dbSLois Curfman McInnes - maxf  - maximum number of function evaluations
3863fee21e36SBarry Smith 
386436851e7fSLois Curfman McInnes   Level: intermediate
386536851e7fSLois Curfman McInnes 
3866dc4c0fb0SBarry Smith   Note:
3867dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3868dc4c0fb0SBarry Smith 
38691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
387033174efeSLois Curfman McInnes @*/
3871d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3872d71ae5a4SJacob Faibussowitsch {
38733a40ed3dSBarry Smith   PetscFunctionBegin;
38740700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
387585385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
387633174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3877c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
387833174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
387933174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
38803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388133174efeSLois Curfman McInnes }
388233174efeSLois Curfman McInnes 
3883e4d06f11SPatrick Farrell /*@
3884e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3885e4d06f11SPatrick Farrell 
3886e4d06f11SPatrick Farrell   Not Collective
3887e4d06f11SPatrick Farrell 
3888e4d06f11SPatrick Farrell   Input Parameters:
3889f6dfbefdSBarry Smith + snes   - the `SNES` context
3890e4d06f11SPatrick Farrell - divtol - divergence tolerance
3891e4d06f11SPatrick Farrell 
3892e4d06f11SPatrick Farrell   Level: intermediate
3893e4d06f11SPatrick Farrell 
38941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3895e4d06f11SPatrick Farrell @*/
3896d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3897d71ae5a4SJacob Faibussowitsch {
3898e4d06f11SPatrick Farrell   PetscFunctionBegin;
3899e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3900e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
39013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3902e4d06f11SPatrick Farrell }
3903e4d06f11SPatrick Farrell 
390433174efeSLois Curfman McInnes /*@
39059b94acceSBarry Smith   SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
39069b94acceSBarry Smith 
3907c3339decSBarry Smith   Logically Collective
3908fee21e36SBarry Smith 
3909c7afd0dbSLois Curfman McInnes   Input Parameters:
3910f6dfbefdSBarry Smith + snes - the `SNES` context
3911c7afd0dbSLois Curfman McInnes - tol  - tolerance
3912c7afd0dbSLois Curfman McInnes 
39139b94acceSBarry Smith   Options Database Key:
39144a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol
39159b94acceSBarry Smith 
391636851e7fSLois Curfman McInnes   Level: intermediate
391736851e7fSLois Curfman McInnes 
39189bcc50f1SBarry Smith   Developer Note:
39199bcc50f1SBarry Smith   Should be SNESTrustRegionSetTolerance()
39209bcc50f1SBarry Smith 
39211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
39229b94acceSBarry Smith @*/
3923d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3924d71ae5a4SJacob Faibussowitsch {
39253a40ed3dSBarry Smith   PetscFunctionBegin;
39260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3927c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
39289b94acceSBarry Smith   snes->deltatol = tol;
39293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39309b94acceSBarry Smith }
39319b94acceSBarry Smith 
39326ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
39336ba87a44SLisandro Dalcin 
3934d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3935d71ae5a4SJacob Faibussowitsch {
3936b271bb04SBarry Smith   PetscDrawLG      lg;
3937b271bb04SBarry Smith   PetscReal        x, y, per;
3938b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3939b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3940b271bb04SBarry Smith   PetscDraw        draw;
3941b271bb04SBarry Smith 
3942459f5d12SBarry Smith   PetscFunctionBegin;
39434d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
39449566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
39459566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39469566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39479566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3948b271bb04SBarry Smith   x = (PetscReal)n;
394977b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
395094c9c6d3SKarl Rupp   else y = -15.0;
39519566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39526934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39539566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39549566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3955b271bb04SBarry Smith   }
3956b271bb04SBarry Smith 
39579566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
39589566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39599566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
3960aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
39619566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3962b271bb04SBarry Smith   x = (PetscReal)n;
3963b271bb04SBarry Smith   y = 100.0 * per;
39649566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39656934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39669566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39679566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3968b271bb04SBarry Smith   }
3969b271bb04SBarry Smith 
39709566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
39719371c9d4SSatish Balay   if (!n) {
39729371c9d4SSatish Balay     prev = rnorm;
39739371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
39749371c9d4SSatish Balay   }
39759566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39769566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3977b271bb04SBarry Smith   x = (PetscReal)n;
3978b271bb04SBarry Smith   y = (prev - rnorm) / prev;
39799566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39806934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39819566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39829566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3983b271bb04SBarry Smith   }
3984b271bb04SBarry Smith 
39859566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
39869566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39879566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39889566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3989b271bb04SBarry Smith   x = (PetscReal)n;
3990b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3991b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
39929566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3993b271bb04SBarry Smith   }
39946934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39959566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39969566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3997b271bb04SBarry Smith   }
3998b271bb04SBarry Smith   prev = rnorm;
39993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4000b271bb04SBarry Smith }
4001b271bb04SBarry Smith 
4002228d79bcSJed Brown /*@
40032d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
40042d157150SStefano Zampini 
40052d157150SStefano Zampini   Collective
40062d157150SStefano Zampini 
40072d157150SStefano Zampini   Input Parameters:
40082d157150SStefano Zampini + snes  - the `SNES` context
40092d157150SStefano Zampini . it    - current iteration
40102d157150SStefano Zampini . xnorm - 2-norm of current iterate
40112d157150SStefano Zampini . snorm - 2-norm of current step
40122d157150SStefano Zampini - fnorm - 2-norm of function
40132d157150SStefano Zampini 
40142d157150SStefano Zampini   Level: developer
40152d157150SStefano Zampini 
40162d157150SStefano Zampini   Note:
4017420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
40182d157150SStefano Zampini   It does not typically need to be called by the user.
40192d157150SStefano Zampini 
4020be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
40212d157150SStefano Zampini @*/
40222d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
40232d157150SStefano Zampini {
40242d157150SStefano Zampini   PetscFunctionBegin;
40252d157150SStefano Zampini   if (!snes->reason) {
40262d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
40272d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
40282d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
40292d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
40302d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
40312d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
40322d157150SStefano Zampini     }
40332d157150SStefano Zampini   }
40342d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
40352d157150SStefano Zampini }
40362d157150SStefano Zampini 
40372d157150SStefano Zampini /*@
4038228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
4039228d79bcSJed Brown 
4040c3339decSBarry Smith   Collective
4041228d79bcSJed Brown 
4042228d79bcSJed Brown   Input Parameters:
4043f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
4044228d79bcSJed Brown . iter  - iteration number
4045228d79bcSJed Brown - rnorm - relative norm of the residual
4046228d79bcSJed Brown 
4047dc4c0fb0SBarry Smith   Level: developer
4048dc4c0fb0SBarry Smith 
4049f6dfbefdSBarry Smith   Note:
4050420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4051228d79bcSJed Brown   It does not typically need to be called by the user.
4052228d79bcSJed Brown 
40531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4054228d79bcSJed Brown @*/
4055d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4056d71ae5a4SJacob Faibussowitsch {
40577a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
40587a03ce2fSLisandro Dalcin 
40597a03ce2fSLisandro Dalcin   PetscFunctionBegin;
40605f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
40619566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
406248a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
40639566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
40643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40657a03ce2fSLisandro Dalcin }
40667a03ce2fSLisandro Dalcin 
40679b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
40689b94acceSBarry Smith 
4069bf388a1fSBarry Smith /*MC
4070f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4071bf388a1fSBarry Smith 
4072bf388a1fSBarry Smith      Synopsis:
4073aaa7dc30SBarry Smith      #include <petscsnes.h>
407437fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4075bf388a1fSBarry Smith 
4076c3339decSBarry Smith      Collective
40771843f636SBarry Smith 
40781843f636SBarry Smith     Input Parameters:
4079f6dfbefdSBarry Smith +    snes - the `SNES` context
4080bf388a1fSBarry Smith .    its - iteration number
4081bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4082bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4083bf388a1fSBarry Smith 
4084878cb397SSatish Balay    Level: advanced
4085878cb397SSatish Balay 
40861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4087bf388a1fSBarry Smith M*/
4088bf388a1fSBarry Smith 
40899b94acceSBarry Smith /*@C
4090a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
40919b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
40929b94acceSBarry Smith   progress.
40939b94acceSBarry Smith 
4094c3339decSBarry Smith   Logically Collective
4095fee21e36SBarry Smith 
4096c7afd0dbSLois Curfman McInnes   Input Parameters:
4097f6dfbefdSBarry Smith + snes           - the `SNES` context
409820f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4099420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4100dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
41019b94acceSBarry Smith 
41029665c990SLois Curfman McInnes   Options Database Keys:
4103f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4104798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4105dc4c0fb0SBarry 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
4106c7afd0dbSLois Curfman McInnes                                 the options database.
41079665c990SLois Curfman McInnes 
4108dc4c0fb0SBarry Smith   Level: intermediate
4109dc4c0fb0SBarry Smith 
4110f6dfbefdSBarry Smith   Note:
41116bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4112f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
41136bc08f3fSLois Curfman McInnes   order in which they were set.
4114639f9d9dSBarry Smith 
4115420bcc1bSBarry Smith   Fortran Note:
4116f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4117025f1a04SBarry Smith 
41181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
41199b94acceSBarry Smith @*/
4120d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4121d71ae5a4SJacob Faibussowitsch {
4122b90d0a6eSBarry Smith   PetscInt  i;
412378064530SBarry Smith   PetscBool identical;
4124b90d0a6eSBarry Smith 
41253a40ed3dSBarry Smith   PetscFunctionBegin;
41260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4127b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
41289566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
41293ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4130649052a6SBarry Smith   }
41315f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
41326e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4133b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4134639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
41353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41369b94acceSBarry Smith }
41379b94acceSBarry Smith 
4138a278d85bSSatish Balay /*@
4139f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
41405cd90555SBarry Smith 
4141c3339decSBarry Smith   Logically Collective
4142c7afd0dbSLois Curfman McInnes 
41432fe279fdSBarry Smith   Input Parameter:
4144f6dfbefdSBarry Smith . snes - the `SNES` context
41455cd90555SBarry Smith 
41461a480d89SAdministrator   Options Database Key:
4147a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4148dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4149c7afd0dbSLois Curfman McInnes     set via the options database
41505cd90555SBarry Smith 
4151dc4c0fb0SBarry Smith   Level: intermediate
4152dc4c0fb0SBarry Smith 
4153f6dfbefdSBarry Smith   Note:
4154f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
41555cd90555SBarry Smith 
41561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
41575cd90555SBarry Smith @*/
4158d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4159d71ae5a4SJacob Faibussowitsch {
4160d952e501SBarry Smith   PetscInt i;
4161d952e501SBarry Smith 
41625cd90555SBarry Smith   PetscFunctionBegin;
41630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4164d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
416548a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4166d952e501SBarry Smith   }
41675cd90555SBarry Smith   snes->numbermonitors = 0;
41683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41695cd90555SBarry Smith }
41705cd90555SBarry Smith 
4171bf388a1fSBarry Smith /*MC
4172bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4173bf388a1fSBarry Smith 
4174bf388a1fSBarry Smith      Synopsis:
4175aaa7dc30SBarry Smith      #include <petscsnes.h>
417637fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4177bf388a1fSBarry Smith 
4178c3339decSBarry Smith      Collective
41791843f636SBarry Smith 
41801843f636SBarry Smith     Input Parameters:
4181f6dfbefdSBarry Smith +    snes - the `SNES` context
4182bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4183bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4184bf388a1fSBarry Smith .    gnorm - 2-norm of current step
41851843f636SBarry Smith .    f - 2-norm of function
41861843f636SBarry Smith -    cctx - [optional] convergence context
41871843f636SBarry Smith 
41881843f636SBarry Smith     Output Parameter:
41891843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4190bf388a1fSBarry Smith 
4191878cb397SSatish Balay    Level: intermediate
4192bf388a1fSBarry Smith 
41931cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4194bf388a1fSBarry Smith M*/
4195bf388a1fSBarry Smith 
41969b94acceSBarry Smith /*@C
41979b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
41989b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
41999b94acceSBarry Smith 
4200c3339decSBarry Smith   Logically Collective
4201fee21e36SBarry Smith 
4202c7afd0dbSLois Curfman McInnes   Input Parameters:
4203f6dfbefdSBarry Smith + snes                        - the `SNES` context
4204e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4205dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4206dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
42079b94acceSBarry Smith 
420836851e7fSLois Curfman McInnes   Level: advanced
420936851e7fSLois Curfman McInnes 
42101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
42119b94acceSBarry Smith @*/
4212d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4213d71ae5a4SJacob Faibussowitsch {
42143a40ed3dSBarry Smith   PetscFunctionBegin;
42150700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4216e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
42171baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4218bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
42197f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
422085385478SLisandro Dalcin   snes->cnvP                  = cctx;
42213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42229b94acceSBarry Smith }
42239b94acceSBarry Smith 
422452baeb72SSatish Balay /*@
4225f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4226184914b5SBarry Smith 
4227184914b5SBarry Smith   Not Collective
4228184914b5SBarry Smith 
4229184914b5SBarry Smith   Input Parameter:
4230f6dfbefdSBarry Smith . snes - the `SNES` context
4231184914b5SBarry Smith 
4232184914b5SBarry Smith   Output Parameter:
4233f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4234184914b5SBarry Smith 
4235f6dfbefdSBarry Smith   Options Database Key:
42366a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
42376a4d7782SBarry Smith 
4238184914b5SBarry Smith   Level: intermediate
4239184914b5SBarry Smith 
4240f6dfbefdSBarry Smith   Note:
4241f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4242184914b5SBarry Smith 
42431cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4244184914b5SBarry Smith @*/
4245d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4246d71ae5a4SJacob Faibussowitsch {
4247184914b5SBarry Smith   PetscFunctionBegin;
42480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42494f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4250184914b5SBarry Smith   *reason = snes->reason;
42513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4252184914b5SBarry Smith }
4253184914b5SBarry Smith 
4254c4421ceaSFande Kong /*@C
4255f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4256c4421ceaSFande Kong 
4257c4421ceaSFande Kong   Not Collective
4258c4421ceaSFande Kong 
4259c4421ceaSFande Kong   Input Parameter:
4260f6dfbefdSBarry Smith . snes - the `SNES` context
4261c4421ceaSFande Kong 
4262c4421ceaSFande Kong   Output Parameter:
4263dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4264c4421ceaSFande Kong 
426599c90e12SSatish Balay   Level: beginner
4266c4421ceaSFande Kong 
42671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4268c4421ceaSFande Kong @*/
4269d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4270d71ae5a4SJacob Faibussowitsch {
4271c4421ceaSFande Kong   PetscFunctionBegin;
4272c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42734f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4274c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
42753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4276c4421ceaSFande Kong }
4277c4421ceaSFande Kong 
427833866048SMatthew G. Knepley /*@
4279f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
428033866048SMatthew G. Knepley 
428133866048SMatthew G. Knepley   Not Collective
428233866048SMatthew G. Knepley 
428333866048SMatthew G. Knepley   Input Parameters:
4284f6dfbefdSBarry Smith + snes   - the `SNES` context
4285f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
428633866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
428733866048SMatthew G. Knepley 
4288f6dfbefdSBarry Smith   Level: developer
4289f6dfbefdSBarry Smith 
4290420bcc1bSBarry Smith   Developer Note:
4291f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
429233866048SMatthew G. Knepley 
42931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
429433866048SMatthew G. Knepley @*/
4295d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4296d71ae5a4SJacob Faibussowitsch {
429733866048SMatthew G. Knepley   PetscFunctionBegin;
429833866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42995f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
430033866048SMatthew G. Knepley   snes->reason = reason;
43013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
430233866048SMatthew G. Knepley }
430333866048SMatthew G. Knepley 
4304c9005455SLois Curfman McInnes /*@
4305420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4306c9005455SLois Curfman McInnes 
4307c3339decSBarry Smith   Logically Collective
4308fee21e36SBarry Smith 
4309c7afd0dbSLois Curfman McInnes   Input Parameters:
4310f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
43118c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4312cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4313420bcc1bSBarry Smith . na    - size of `a` and `its`
4314f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4315758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4316c7afd0dbSLois Curfman McInnes 
4317dc4c0fb0SBarry Smith   Level: intermediate
4318dc4c0fb0SBarry Smith 
4319308dcc3eSBarry Smith   Notes:
4320dc4c0fb0SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4321308dcc3eSBarry Smith   default array of length 10000 is allocated.
4322308dcc3eSBarry Smith 
4323c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4324c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4325c9005455SLois Curfman McInnes   during the section of code that is being timed.
4326c9005455SLois Curfman McInnes 
4327420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4328420bcc1bSBarry Smith 
43291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4330c9005455SLois Curfman McInnes @*/
4331d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4332d71ae5a4SJacob Faibussowitsch {
43333a40ed3dSBarry Smith   PetscFunctionBegin;
43340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43354f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
43364f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
43377a1ec6d4SBarry Smith   if (!a) {
4338308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
43399566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4340071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4341308dcc3eSBarry Smith   }
4342c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4343758f92a0SBarry Smith   snes->conv_hist_its   = its;
4344115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4345a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4346758f92a0SBarry Smith   snes->conv_hist_reset = reset;
43473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4348758f92a0SBarry Smith }
4349758f92a0SBarry Smith 
4350d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4351c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4352c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
435399e0435eSBarry Smith 
4354d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4355d71ae5a4SJacob Faibussowitsch {
4356308dcc3eSBarry Smith   mxArray   *mat;
4357308dcc3eSBarry Smith   PetscInt   i;
4358308dcc3eSBarry Smith   PetscReal *ar;
4359308dcc3eSBarry Smith 
4360308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4361308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4362f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
436311cc89d2SBarry Smith   return mat;
4364308dcc3eSBarry Smith }
4365308dcc3eSBarry Smith #endif
4366308dcc3eSBarry Smith 
43670c4c9dddSBarry Smith /*@C
4368420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4369758f92a0SBarry Smith 
43703f9fe445SBarry Smith   Not Collective
4371758f92a0SBarry Smith 
4372758f92a0SBarry Smith   Input Parameter:
4373f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4374758f92a0SBarry Smith 
4375758f92a0SBarry Smith   Output Parameters:
4376f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4377758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4378758f92a0SBarry Smith          negative if not converged) for each solve.
437920f4b53cSBarry Smith - na  - size of `a` and `its`
4380758f92a0SBarry Smith 
4381dc4c0fb0SBarry Smith   Level: intermediate
4382dc4c0fb0SBarry Smith 
438320f4b53cSBarry Smith   Note:
438420f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
438520f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
438620f4b53cSBarry Smith   during the section of code that is being timed.
438720f4b53cSBarry Smith 
4388420bcc1bSBarry Smith   Fortran Note:
4389758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4390dc4c0fb0SBarry Smith .vb
4391dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4392dc4c0fb0SBarry Smith .ve
4393758f92a0SBarry Smith 
43941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4395758f92a0SBarry Smith @*/
4396d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4397d71ae5a4SJacob Faibussowitsch {
4398758f92a0SBarry Smith   PetscFunctionBegin;
43990700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4400758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4401758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4402115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
44033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4404c9005455SLois Curfman McInnes }
4405c9005455SLois Curfman McInnes 
4406ac226902SBarry Smith /*@C
440776b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4408eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
44097e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
441076b2cf59SMatthew Knepley 
4411c3339decSBarry Smith   Logically Collective
441276b2cf59SMatthew Knepley 
441376b2cf59SMatthew Knepley   Input Parameters:
4414a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4415a2b725a8SWilliam Gropp - func - The function
441676b2cf59SMatthew Knepley 
441720f4b53cSBarry Smith   Calling sequence of `func`:
441820f4b53cSBarry Smith + snes - the nonlinear solver context
441920f4b53cSBarry Smith - step - The current step of the iteration
442076b2cf59SMatthew Knepley 
4421fe97e370SBarry Smith   Level: advanced
4422fe97e370SBarry Smith 
4423420bcc1bSBarry Smith   Notes:
4424f6dfbefdSBarry 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
4425f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
4426fe97e370SBarry Smith   This is not used by most users.
442776b2cf59SMatthew Knepley 
4428aaa8cc7dSPierre 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.
44296b7fb656SBarry Smith 
4430e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4431db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
443276b2cf59SMatthew Knepley @*/
44330b4db180SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES snes, PetscInt step))
4434d71ae5a4SJacob Faibussowitsch {
443576b2cf59SMatthew Knepley   PetscFunctionBegin;
44360700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4437e7788613SBarry Smith   snes->ops->update = func;
44383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
443976b2cf59SMatthew Knepley }
444076b2cf59SMatthew Knepley 
444191f3e32bSBarry Smith /*@C
4442f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
44432a359c20SBarry Smith 
4444c3339decSBarry Smith   Collective
44452a359c20SBarry Smith 
4446e4094ef1SJacob Faibussowitsch   Input Parameters:
4447f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
44482a359c20SBarry Smith - viewer - the viewer to display the reason
44492a359c20SBarry Smith 
44502a359c20SBarry Smith   Options Database Keys:
4451ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4452ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4453eafd5ff0SAlex Lindsay 
4454420bcc1bSBarry Smith   Level: beginner
4455420bcc1bSBarry Smith 
4456f6dfbefdSBarry Smith   Note:
4457f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4458f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
44592a359c20SBarry Smith 
44601cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4461f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4462f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4463db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
44642a359c20SBarry Smith @*/
4465d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4466d71ae5a4SJacob Faibussowitsch {
446775cca76cSMatthew G. Knepley   PetscViewerFormat format;
44682a359c20SBarry Smith   PetscBool         isAscii;
44692a359c20SBarry Smith 
44702a359c20SBarry Smith   PetscFunctionBegin;
447119a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
44729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
44732a359c20SBarry Smith   if (isAscii) {
44749566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
447565bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
447675cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
447775cca76cSMatthew G. Knepley       DM       dm;
447875cca76cSMatthew G. Knepley       Vec      u;
447975cca76cSMatthew G. Knepley       PetscDS  prob;
448075cca76cSMatthew G. Knepley       PetscInt Nf, f;
448195cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
448295cbbfd3SMatthew G. Knepley       void    **exactCtx;
448375cca76cSMatthew G. Knepley       PetscReal error;
448475cca76cSMatthew G. Knepley 
44859566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
44869566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
44879566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
44889566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
44899566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
44909566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
44919566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
44929566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
44939566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
449463a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
449575cca76cSMatthew G. Knepley     }
4496eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
44972a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
449863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
44992a359c20SBarry Smith       } else {
450063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
45012a359c20SBarry Smith       }
4502eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
45032a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
450463a3b9bcSJacob 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));
45052a359c20SBarry Smith       } else {
450663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
45072a359c20SBarry Smith       }
45082a359c20SBarry Smith     }
450965bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
45102a359c20SBarry Smith   }
45113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45122a359c20SBarry Smith }
45132a359c20SBarry Smith 
4514c4421ceaSFande Kong /*@C
4515c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4516aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4517c4421ceaSFande Kong 
4518c3339decSBarry Smith   Logically Collective
4519c4421ceaSFande Kong 
4520c4421ceaSFande Kong   Input Parameters:
4521f6dfbefdSBarry Smith + snes              - the `SNES` context
4522420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4523420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4524420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`)
4525420bcc1bSBarry Smith 
4526420bcc1bSBarry Smith   Calling sequence of `f`:
4527420bcc1bSBarry Smith + snes - the `SNES` context
4528420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function
4529420bcc1bSBarry Smith 
4530420bcc1bSBarry Smith   Calling sequence of `reasonviewerdestroy`:
4531420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function
4532c4421ceaSFande Kong 
4533c4421ceaSFande Kong   Options Database Keys:
4534f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4535420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4536420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4537c4421ceaSFande Kong 
4538dc4c0fb0SBarry Smith   Level: intermediate
4539dc4c0fb0SBarry Smith 
4540f6dfbefdSBarry Smith   Note:
4541c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4542f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4543c4421ceaSFande Kong   order in which they were set.
4544c4421ceaSFande Kong 
45451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4546c4421ceaSFande Kong @*/
4547420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx))
4548d71ae5a4SJacob Faibussowitsch {
4549c4421ceaSFande Kong   PetscInt  i;
4550c4421ceaSFande Kong   PetscBool identical;
4551c4421ceaSFande Kong 
4552c4421ceaSFande Kong   PetscFunctionBegin;
4553c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4554c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
45559566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
45563ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4557c4421ceaSFande Kong   }
45585f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4559c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4560c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4561c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
45623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4563c4421ceaSFande Kong }
4564c4421ceaSFande Kong 
456591f3e32bSBarry Smith /*@
4566420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4567c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
45682a359c20SBarry Smith 
4569c3339decSBarry Smith   Collective
45702a359c20SBarry Smith 
45712fe279fdSBarry Smith   Input Parameter:
4572f6dfbefdSBarry Smith . snes - the `SNES` object
45732a359c20SBarry Smith 
4574f6dfbefdSBarry Smith   Level: advanced
45752a359c20SBarry Smith 
45761cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4577f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
45782a359c20SBarry Smith @*/
4579d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4580d71ae5a4SJacob Faibussowitsch {
45812a359c20SBarry Smith   PetscViewer       viewer;
45822a359c20SBarry Smith   PetscBool         flg;
45832a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
45842a359c20SBarry Smith   PetscViewerFormat format;
4585c4421ceaSFande Kong   PetscInt          i;
45862a359c20SBarry Smith 
45872a359c20SBarry Smith   PetscFunctionBegin;
45883ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
45892a359c20SBarry Smith   incall = PETSC_TRUE;
4590c4421ceaSFande Kong 
4591c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
459248a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4593c4421ceaSFande Kong 
4594c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
45959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
45962a359c20SBarry Smith   if (flg) {
45979566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
45989566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
45999566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
4600cd791dc2SBarry Smith     PetscCall(PetscOptionsRestoreViewer(&viewer));
46012a359c20SBarry Smith   }
46022a359c20SBarry Smith   incall = PETSC_FALSE;
46033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46042a359c20SBarry Smith }
46052a359c20SBarry Smith 
4606487a658cSBarry Smith /*@
4607f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
46089b94acceSBarry Smith 
4609c3339decSBarry Smith   Collective
4610c7afd0dbSLois Curfman McInnes 
4611b2002411SLois Curfman McInnes   Input Parameters:
4612f6dfbefdSBarry Smith + snes - the `SNES` context
4613dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
461485385478SLisandro Dalcin - x    - the solution vector.
46159b94acceSBarry Smith 
4616dc4c0fb0SBarry Smith   Level: beginner
4617dc4c0fb0SBarry Smith 
4618f6dfbefdSBarry Smith   Note:
4619420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4620420bcc1bSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
46218ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4622f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
46238ddd3da0SLois Curfman McInnes 
46241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4625db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4626420bcc1bSBarry Smith           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
46279b94acceSBarry Smith @*/
4628d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4629d71ae5a4SJacob Faibussowitsch {
4630ace3abfcSBarry Smith   PetscBool flg;
4631efd51863SBarry Smith   PetscInt  grid;
46320298fd71SBarry Smith   Vec       xcreated = NULL;
4633caa4e7f2SJed Brown   DM        dm;
4634052efed2SBarry Smith 
46353a40ed3dSBarry Smith   PetscFunctionBegin;
46360700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4637a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4638a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
46390700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
464085385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
464185385478SLisandro Dalcin 
464234b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
464306fc46c8SMatthew G. Knepley   {
464406fc46c8SMatthew G. Knepley     PetscViewer       viewer;
464506fc46c8SMatthew G. Knepley     PetscViewerFormat format;
46467c88af5aSMatthew G. Knepley     PetscInt          num;
464706fc46c8SMatthew G. Knepley     PetscBool         flg;
464806fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
464906fc46c8SMatthew G. Knepley 
465006fc46c8SMatthew G. Knepley     if (!incall) {
465134b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
46529566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
465306fc46c8SMatthew G. Knepley       if (flg) {
465406fc46c8SMatthew G. Knepley         PetscConvEst conv;
465546079b62SMatthew G. Knepley         DM           dm;
465646079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
465746079b62SMatthew G. Knepley         PetscInt     Nf;
465806fc46c8SMatthew G. Knepley 
465906fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
46609566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
46619566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
46629566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
46639566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
46649566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
46659566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
46669566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
46679566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
46689566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
46699566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
46709566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4671cd791dc2SBarry Smith         PetscCall(PetscOptionsRestoreViewer(&viewer));
46729566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
46739566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
467406fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
467506fc46c8SMatthew G. Knepley       }
467634b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4677b2588ea6SMatthew G. Knepley       num = 1;
46789566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
467934b4d3a8SMatthew G. Knepley       if (flg) {
468034b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
468134b4d3a8SMatthew G. Knepley 
468234b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
46839566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46849566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46859566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46869566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46879566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46889566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
46899566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
469034b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
469134b4d3a8SMatthew G. Knepley       }
46927c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
46937c88af5aSMatthew G. Knepley       num = 0;
46949566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
46957c88af5aSMatthew G. Knepley       if (num) {
46967c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
46977c88af5aSMatthew G. Knepley 
46987c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
46999566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
47009566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
47019566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
47029566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
47039566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
47049566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
47059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
47067c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
47077c88af5aSMatthew G. Knepley       }
470806fc46c8SMatthew G. Knepley     }
470906fc46c8SMatthew G. Knepley   }
4710ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4711caa4e7f2SJed Brown   if (!x) {
47129566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
47139566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4714a69afd8bSBarry Smith     x = xcreated;
4715a69afd8bSBarry Smith   }
47169566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4717f05ece33SBarry Smith 
47189566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4719efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
472085385478SLisandro Dalcin     /* set solution vector */
47219566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
47229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
472385385478SLisandro Dalcin     snes->vec_sol = x;
47249566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4725caa4e7f2SJed Brown 
4726caa4e7f2SJed Brown     /* set affine vector if provided */
47279566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
47289566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
472985385478SLisandro Dalcin     snes->vec_rhs = b;
473085385478SLisandro Dalcin 
47315f80ce2aSJacob 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");
47325f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4733dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4734aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
47359566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
47369566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
47373f149594SLisandro Dalcin 
47387eee914bSBarry Smith     if (!grid) {
47399927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4740dd568438SSatish Balay     }
4741d25893d9SBarry Smith 
4742abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
47439371c9d4SSatish Balay     if (snes->counters_reset) {
47449371c9d4SSatish Balay       snes->nfuncs      = 0;
47459371c9d4SSatish Balay       snes->linear_its  = 0;
47469371c9d4SSatish Balay       snes->numFailures = 0;
47479371c9d4SSatish Balay     }
4748d5e45103SBarry Smith 
47492d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
47509566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4751dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
47529566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
47532d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4754422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
47553f149594SLisandro Dalcin 
475637ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
475737ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
475837ec4e1aSPeter Brune 
47599566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
47609566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4761c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
47629566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
47635968eb51SBarry Smith 
47645f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
47659c8e83a9SBarry Smith     if (snes->reason < 0) break;
4766efd51863SBarry Smith     if (grid < snes->gridsequence) {
4767efd51863SBarry Smith       DM  fine;
4768efd51863SBarry Smith       Vec xnew;
4769efd51863SBarry Smith       Mat interp;
4770efd51863SBarry Smith 
47719566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
47725f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
47739566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
47749566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
47759566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
47769566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
47779566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4778efd51863SBarry Smith       x = xnew;
4779efd51863SBarry Smith 
47809566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
47819566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
47829566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
47839566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
47849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4785efd51863SBarry Smith     }
4786efd51863SBarry Smith   }
47879566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
47889566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
47899566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
47909566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
47913f7e2da0SPeter Brune 
47929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
47939566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
47943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47959b94acceSBarry Smith }
47969b94acceSBarry Smith 
47979b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
47989b94acceSBarry Smith 
479982bf6240SBarry Smith /*@C
48004b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
48019b94acceSBarry Smith 
4802c3339decSBarry Smith   Collective
4803fee21e36SBarry Smith 
4804c7afd0dbSLois Curfman McInnes   Input Parameters:
4805f6dfbefdSBarry Smith + snes - the `SNES` context
4806454a90a3SBarry Smith - type - a known method
4807c7afd0dbSLois Curfman McInnes 
4808c7afd0dbSLois Curfman McInnes   Options Database Key:
4809454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
481004d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4811ae12b187SLois Curfman McInnes 
4812dc4c0fb0SBarry Smith   Level: intermediate
4813dc4c0fb0SBarry Smith 
48149b94acceSBarry Smith   Notes:
4815e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4816f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4817c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
48184a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4819c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
48209b94acceSBarry Smith 
4821f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4822f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4823ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4824ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4825f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4826ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4827ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4828ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4829ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4830b0a32e0cSBarry Smith   appropriate method.
483136851e7fSLois Curfman McInnes 
4832420bcc1bSBarry Smith   Developer Note:
4833f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4834f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
48358f6c3df8SBarry Smith 
48361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
48379b94acceSBarry Smith @*/
4838d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4839d71ae5a4SJacob Faibussowitsch {
4840ace3abfcSBarry Smith   PetscBool match;
48415f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
48423a40ed3dSBarry Smith 
48433a40ed3dSBarry Smith   PetscFunctionBegin;
48440700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48454f572ea9SToby Isaac   PetscAssertPointer(type, 2);
484682bf6240SBarry Smith 
48479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
48483ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
484992ff6ae8SBarry Smith 
48509566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
48516adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
485275396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4853dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
485475396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
48559e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
48569e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
48579e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
48589e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
48599e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
48607fe760d5SStefano Zampini 
48617fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
48629566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
48637fe760d5SStefano Zampini 
486475396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
486575396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4866f5af7f23SKarl Rupp 
48679566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
48689566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
48693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48709b94acceSBarry Smith }
48719b94acceSBarry Smith 
48729b94acceSBarry Smith /*@C
4873f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
48749b94acceSBarry Smith 
4875c7afd0dbSLois Curfman McInnes   Not Collective
4876c7afd0dbSLois Curfman McInnes 
48779b94acceSBarry Smith   Input Parameter:
48784b0e389bSBarry Smith . snes - nonlinear solver context
48799b94acceSBarry Smith 
48809b94acceSBarry Smith   Output Parameter:
4881f6dfbefdSBarry Smith . type - `SNES` method (a character string)
48829b94acceSBarry Smith 
488336851e7fSLois Curfman McInnes   Level: intermediate
488436851e7fSLois Curfman McInnes 
48851cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
48869b94acceSBarry Smith @*/
4887d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4888d71ae5a4SJacob Faibussowitsch {
48893a40ed3dSBarry Smith   PetscFunctionBegin;
48900700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48914f572ea9SToby Isaac   PetscAssertPointer(type, 2);
48927adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
48933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48949b94acceSBarry Smith }
48959b94acceSBarry Smith 
48963cd8a7caSMatthew G. Knepley /*@
4897f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
48983cd8a7caSMatthew G. Knepley 
4899c3339decSBarry Smith   Logically Collective
49003cd8a7caSMatthew G. Knepley 
49013cd8a7caSMatthew G. Knepley   Input Parameters:
4902f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
49033cd8a7caSMatthew G. Knepley - u    - the solution vector
49043cd8a7caSMatthew G. Knepley 
49053cd8a7caSMatthew G. Knepley   Level: beginner
49063cd8a7caSMatthew G. Knepley 
49071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
49083cd8a7caSMatthew G. Knepley @*/
4909d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4910d71ae5a4SJacob Faibussowitsch {
49113cd8a7caSMatthew G. Knepley   DM dm;
49123cd8a7caSMatthew G. Knepley 
49133cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
49143cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49153cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
49169566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
49179566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
49183cd8a7caSMatthew G. Knepley 
49193cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
49203cd8a7caSMatthew G. Knepley 
49219566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49229566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
49233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49243cd8a7caSMatthew G. Knepley }
49253cd8a7caSMatthew G. Knepley 
492652baeb72SSatish Balay /*@
49279b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
4928f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
49299b94acceSBarry Smith 
4930420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4931c7afd0dbSLois Curfman McInnes 
49329b94acceSBarry Smith   Input Parameter:
4933f6dfbefdSBarry Smith . snes - the `SNES` context
49349b94acceSBarry Smith 
49359b94acceSBarry Smith   Output Parameter:
49369b94acceSBarry Smith . x - the solution
49379b94acceSBarry Smith 
493870e92668SMatthew Knepley   Level: intermediate
493936851e7fSLois Curfman McInnes 
49401cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
49419b94acceSBarry Smith @*/
4942d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4943d71ae5a4SJacob Faibussowitsch {
49443a40ed3dSBarry Smith   PetscFunctionBegin;
49450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49464f572ea9SToby Isaac   PetscAssertPointer(x, 2);
494785385478SLisandro Dalcin   *x = snes->vec_sol;
49483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
494970e92668SMatthew Knepley }
495070e92668SMatthew Knepley 
495152baeb72SSatish Balay /*@
49529b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
49539b94acceSBarry Smith   stored.
49549b94acceSBarry Smith 
4955420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4956c7afd0dbSLois Curfman McInnes 
49579b94acceSBarry Smith   Input Parameter:
4958f6dfbefdSBarry Smith . snes - the `SNES` context
49599b94acceSBarry Smith 
49609b94acceSBarry Smith   Output Parameter:
49619b94acceSBarry Smith . x - the solution update
49629b94acceSBarry Smith 
496336851e7fSLois Curfman McInnes   Level: advanced
496436851e7fSLois Curfman McInnes 
49651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
49669b94acceSBarry Smith @*/
4967d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4968d71ae5a4SJacob Faibussowitsch {
49693a40ed3dSBarry Smith   PetscFunctionBegin;
49700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49714f572ea9SToby Isaac   PetscAssertPointer(x, 2);
497285385478SLisandro Dalcin   *x = snes->vec_sol_update;
49733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49749b94acceSBarry Smith }
49759b94acceSBarry Smith 
49769b94acceSBarry Smith /*@C
4977f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
49789b94acceSBarry Smith 
4979420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
4980c7afd0dbSLois Curfman McInnes 
49819b94acceSBarry Smith   Input Parameter:
4982f6dfbefdSBarry Smith . snes - the `SNES` context
49839b94acceSBarry Smith 
4984d8d19677SJose E. Roman   Output Parameters:
4985dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
49868434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
4987dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
49889b94acceSBarry Smith 
498936851e7fSLois Curfman McInnes   Level: advanced
499036851e7fSLois Curfman McInnes 
4991f6dfbefdSBarry Smith   Note:
4992dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
499304edfde5SBarry Smith 
49948434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
49959b94acceSBarry Smith @*/
49968434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
4997d71ae5a4SJacob Faibussowitsch {
49986cab3a1bSJed Brown   DM dm;
4999a63bb30eSJed Brown 
50003a40ed3dSBarry Smith   PetscFunctionBegin;
50010700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5002a63bb30eSJed Brown   if (r) {
5003a63bb30eSJed Brown     if (!snes->vec_func) {
5004a63bb30eSJed Brown       if (snes->vec_rhs) {
50059566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5006a63bb30eSJed Brown       } else if (snes->vec_sol) {
50079566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5008a63bb30eSJed Brown       } else if (snes->dm) {
50099566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5010a63bb30eSJed Brown       }
5011a63bb30eSJed Brown     }
5012a63bb30eSJed Brown     *r = snes->vec_func;
5013a63bb30eSJed Brown   }
50149566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50159566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
50163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50179b94acceSBarry Smith }
50189b94acceSBarry Smith 
5019c79ef259SPeter Brune /*@C
502037fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5021c79ef259SPeter Brune 
5022c79ef259SPeter Brune   Input Parameter:
5023f6dfbefdSBarry Smith . snes - the `SNES` context
5024c79ef259SPeter Brune 
5025d8d19677SJose E. Roman   Output Parameters:
50268434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5027dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5028c79ef259SPeter Brune 
5029c79ef259SPeter Brune   Level: advanced
5030c79ef259SPeter Brune 
50318434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5032c79ef259SPeter Brune @*/
50338434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5034d71ae5a4SJacob Faibussowitsch {
50356cab3a1bSJed Brown   DM dm;
50366cab3a1bSJed Brown 
5037646217ecSPeter Brune   PetscFunctionBegin;
5038646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50399566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50409566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
50413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5042646217ecSPeter Brune }
5043646217ecSPeter Brune 
50443c7409f5SSatish Balay /*@C
50453c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5046f6dfbefdSBarry Smith   `SNES` options in the database.
50473c7409f5SSatish Balay 
5048c3339decSBarry Smith   Logically Collective
5049fee21e36SBarry Smith 
5050d8d19677SJose E. Roman   Input Parameters:
5051f6dfbefdSBarry Smith + snes   - the `SNES` context
5052c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5053c7afd0dbSLois Curfman McInnes 
5054dc4c0fb0SBarry Smith   Level: advanced
5055dc4c0fb0SBarry Smith 
5056f6dfbefdSBarry Smith   Note:
5057a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5058c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5059d850072dSLois Curfman McInnes 
50601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
50613c7409f5SSatish Balay @*/
5062d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5063d71ae5a4SJacob Faibussowitsch {
50643a40ed3dSBarry Smith   PetscFunctionBegin;
50650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50669566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
50679566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
506835f5d045SPeter Brune   if (snes->linesearch) {
50699566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50709566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
507135f5d045SPeter Brune   }
50729566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
50733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50743c7409f5SSatish Balay }
50753c7409f5SSatish Balay 
50763c7409f5SSatish Balay /*@C
5077f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5078f6dfbefdSBarry Smith   `SNES` options in the database.
50793c7409f5SSatish Balay 
5080c3339decSBarry Smith   Logically Collective
5081fee21e36SBarry Smith 
5082c7afd0dbSLois Curfman McInnes   Input Parameters:
5083f6dfbefdSBarry Smith + snes   - the `SNES` context
5084c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5085c7afd0dbSLois Curfman McInnes 
5086dc4c0fb0SBarry Smith   Level: advanced
5087dc4c0fb0SBarry Smith 
5088f6dfbefdSBarry Smith   Note:
5089a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5090c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5091d850072dSLois Curfman McInnes 
50921cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
50933c7409f5SSatish Balay @*/
5094d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5095d71ae5a4SJacob Faibussowitsch {
50963a40ed3dSBarry Smith   PetscFunctionBegin;
50970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50989566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
50999566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
510035f5d045SPeter Brune   if (snes->linesearch) {
51019566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51029566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
510335f5d045SPeter Brune   }
51049566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
51053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51063c7409f5SSatish Balay }
51073c7409f5SSatish Balay 
51089ab63eb5SSatish Balay /*@C
5109f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5110f6dfbefdSBarry Smith   `SNES` options in the database.
51113c7409f5SSatish Balay 
5112c7afd0dbSLois Curfman McInnes   Not Collective
5113c7afd0dbSLois Curfman McInnes 
51143c7409f5SSatish Balay   Input Parameter:
5115f6dfbefdSBarry Smith . snes - the `SNES` context
51163c7409f5SSatish Balay 
51173c7409f5SSatish Balay   Output Parameter:
51183c7409f5SSatish Balay . prefix - pointer to the prefix string used
51193c7409f5SSatish Balay 
512036851e7fSLois Curfman McInnes   Level: advanced
512136851e7fSLois Curfman McInnes 
5122420bcc1bSBarry Smith   Fortran Note:
5123dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5124dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5125dc4c0fb0SBarry Smith 
51261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
51273c7409f5SSatish Balay @*/
5128d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5129d71ae5a4SJacob Faibussowitsch {
51303a40ed3dSBarry Smith   PetscFunctionBegin;
51310700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51329566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
51333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51343c7409f5SSatish Balay }
51353c7409f5SSatish Balay 
51363cea93caSBarry Smith /*@C
51371c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
51381c84c290SBarry Smith 
513920f4b53cSBarry Smith   Not Collective
51401c84c290SBarry Smith 
51411c84c290SBarry Smith   Input Parameters:
514220f4b53cSBarry Smith + sname    - name of a new user-defined solver
514320f4b53cSBarry Smith - function - routine to create method context
51441c84c290SBarry Smith 
5145dc4c0fb0SBarry Smith   Level: advanced
5146dc4c0fb0SBarry Smith 
5147f6dfbefdSBarry Smith   Note:
5148f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
51491c84c290SBarry Smith 
5150e4094ef1SJacob Faibussowitsch   Example Usage:
51511c84c290SBarry Smith .vb
5152bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
51531c84c290SBarry Smith .ve
51541c84c290SBarry Smith 
51551c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
51561c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
51571c84c290SBarry Smith   or at runtime via the option
51581c84c290SBarry Smith $     -snes_type my_solver
51591c84c290SBarry Smith 
51601cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
51613cea93caSBarry Smith @*/
5162d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5163d71ae5a4SJacob Faibussowitsch {
5164b2002411SLois Curfman McInnes   PetscFunctionBegin;
51659566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
51669566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
51673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5168b2002411SLois Curfman McInnes }
5169da9b6338SBarry Smith 
5170d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5171d71ae5a4SJacob Faibussowitsch {
517277431f27SBarry Smith   PetscInt    N, i, j;
5173da9b6338SBarry Smith   Vec         u, uh, fh;
5174da9b6338SBarry Smith   PetscScalar value;
5175da9b6338SBarry Smith   PetscReal   norm;
5176da9b6338SBarry Smith 
5177da9b6338SBarry Smith   PetscFunctionBegin;
51789566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
51799566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
51809566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5181da9b6338SBarry Smith 
5182da9b6338SBarry Smith   /* currently only works for sequential */
51839566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
51849566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5185da9b6338SBarry Smith   for (i = 0; i < N; i++) {
51869566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
518763a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5188da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
51898b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
51909566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
51919566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
51929566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
519363a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5194da9b6338SBarry Smith       value = -value;
51959566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5196da9b6338SBarry Smith     }
5197da9b6338SBarry Smith   }
51989566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
51999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
52003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5201da9b6338SBarry Smith }
520271f87433Sdalcinl 
520371f87433Sdalcinl /*@
5204f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
520571f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
520671f87433Sdalcinl   Newton method.
520771f87433Sdalcinl 
5208c3339decSBarry Smith   Logically Collective
520971f87433Sdalcinl 
521071f87433Sdalcinl   Input Parameters:
5211f6dfbefdSBarry Smith + snes - `SNES` context
5212f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
521371f87433Sdalcinl 
5214f6dfbefdSBarry Smith   Options Database Keys:
521564ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
521664ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
521764ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
521864ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
521964ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
522064ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
522164ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
522264ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
522364ba62caSBarry Smith 
5224dc4c0fb0SBarry Smith   Level: advanced
5225dc4c0fb0SBarry Smith 
5226f6dfbefdSBarry Smith   Note:
5227f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
522871f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
52291d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
523071f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
523171f87433Sdalcinl   solver.
523271f87433Sdalcinl 
52331cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
523471f87433Sdalcinl @*/
5235d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5236d71ae5a4SJacob Faibussowitsch {
523771f87433Sdalcinl   PetscFunctionBegin;
52380700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5239acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
524071f87433Sdalcinl   snes->ksp_ewconv = flag;
52413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
524271f87433Sdalcinl }
524371f87433Sdalcinl 
524471f87433Sdalcinl /*@
5245f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
524671f87433Sdalcinl   for computing relative tolerance for linear solvers within an
524771f87433Sdalcinl   inexact Newton method.
524871f87433Sdalcinl 
524971f87433Sdalcinl   Not Collective
525071f87433Sdalcinl 
525171f87433Sdalcinl   Input Parameter:
5252f6dfbefdSBarry Smith . snes - `SNES` context
525371f87433Sdalcinl 
525471f87433Sdalcinl   Output Parameter:
5255f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
525671f87433Sdalcinl 
525771f87433Sdalcinl   Level: advanced
525871f87433Sdalcinl 
52591cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
526071f87433Sdalcinl @*/
5261d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5262d71ae5a4SJacob Faibussowitsch {
526371f87433Sdalcinl   PetscFunctionBegin;
52640700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52654f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
526671f87433Sdalcinl   *flag = snes->ksp_ewconv;
52673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
526871f87433Sdalcinl }
526971f87433Sdalcinl 
527071f87433Sdalcinl /*@
5271fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
527271f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
527371f87433Sdalcinl   Newton method.
527471f87433Sdalcinl 
5275c3339decSBarry Smith   Logically Collective
527671f87433Sdalcinl 
527771f87433Sdalcinl   Input Parameters:
5278f6dfbefdSBarry Smith + snes      - `SNES` context
52790f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
528071f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
528171f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
528271f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
528371f87433Sdalcinl              (0 <= gamma2 <= 1)
528471f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
528571f87433Sdalcinl . alpha2    - power for safeguard
528671f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
528771f87433Sdalcinl 
5288dc4c0fb0SBarry Smith   Level: advanced
5289dc4c0fb0SBarry Smith 
5290f6dfbefdSBarry Smith   Notes:
529171f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
529271f87433Sdalcinl 
5293f6dfbefdSBarry Smith   Use `PETSC_DEFAULT` to retain the default for any of the parameters.
529471f87433Sdalcinl 
52951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
529671f87433Sdalcinl @*/
5297d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5298d71ae5a4SJacob Faibussowitsch {
5299fa9f3622SBarry Smith   SNESKSPEW *kctx;
53005fd66863SKarl Rupp 
530171f87433Sdalcinl   PetscFunctionBegin;
53020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5303fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53045f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5305c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5306c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5307c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5308c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5309c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5310c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5311c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
531271f87433Sdalcinl 
531371f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
531413bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
531513bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
531613bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
531713bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
531813bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
531913bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
532071f87433Sdalcinl 
53210f0abf79SStefano 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);
53220b121fc5SBarry 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);
53230b121fc5SBarry 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);
53240b121fc5SBarry 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);
53250b121fc5SBarry 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);
53260b121fc5SBarry 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);
53273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
532871f87433Sdalcinl }
532971f87433Sdalcinl 
533071f87433Sdalcinl /*@
5331fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
533271f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
533371f87433Sdalcinl   Newton method.
533471f87433Sdalcinl 
533571f87433Sdalcinl   Not Collective
533671f87433Sdalcinl 
533797bb3fdcSJose E. Roman   Input Parameter:
5338f6dfbefdSBarry Smith . snes - `SNES` context
533971f87433Sdalcinl 
534071f87433Sdalcinl   Output Parameters:
53410f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
534271f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
534371f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5344bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
534571f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
534671f87433Sdalcinl . alpha2    - power for safeguard
534771f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
534871f87433Sdalcinl 
534971f87433Sdalcinl   Level: advanced
535071f87433Sdalcinl 
53511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
535271f87433Sdalcinl @*/
5353d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5354d71ae5a4SJacob Faibussowitsch {
5355fa9f3622SBarry Smith   SNESKSPEW *kctx;
53565fd66863SKarl Rupp 
535771f87433Sdalcinl   PetscFunctionBegin;
53580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5359fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53605f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
536171f87433Sdalcinl   if (version) *version = kctx->version;
536271f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
536371f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
536471f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
536571f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
536671f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
536771f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
53683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536971f87433Sdalcinl }
537071f87433Sdalcinl 
53715c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5372d71ae5a4SJacob Faibussowitsch {
53735c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5374fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
537571f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
537671f87433Sdalcinl 
537771f87433Sdalcinl   PetscFunctionBegin;
53783ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
537930058271SDmitry Karpeev   if (!snes->iter) {
538030058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
53819566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
53820f0abf79SStefano Zampini   } else {
53830fdf79fbSJacob 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);
538471f87433Sdalcinl     if (kctx->version == 1) {
53850f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
538685ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
538771f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
538871f87433Sdalcinl     } else if (kctx->version == 2) {
538985ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
539085ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
539171f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
539271f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
539385ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
539471f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
539585ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
539671f87433Sdalcinl       stol = PetscMax(rtol, stol);
539771f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
539871f87433Sdalcinl       /* safeguard: avoid oversolving */
539930058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
540071f87433Sdalcinl       stol = PetscMax(rtol, stol);
540171f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
54020fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
54030fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
54040f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
54050f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
54060f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
54070f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
54080f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
54090f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
54100f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
54110f0abf79SStefano Zampini 
5412a4598233SStefano 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;
54130f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
54140f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
54150f0abf79SStefano Zampini       kctx->rk_last     = rk;
54160fdf79fbSJacob Faibussowitsch     }
54170f0abf79SStefano Zampini   }
54180f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
541971f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
54209566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
542163a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
54223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
542371f87433Sdalcinl }
542471f87433Sdalcinl 
54255c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5426d71ae5a4SJacob Faibussowitsch {
54275c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5428fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
542971f87433Sdalcinl   PCSide     pcside;
543071f87433Sdalcinl   Vec        lres;
543171f87433Sdalcinl 
543271f87433Sdalcinl   PetscFunctionBegin;
54333ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
54349566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
543571dbe336SPeter Brune   kctx->norm_last = snes->norm;
54360f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
54374f00ce20SMatthew G. Knepley     PC        pc;
54380f0abf79SStefano Zampini     PetscBool getRes;
54394f00ce20SMatthew G. Knepley 
54409566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
54410f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
54420f0abf79SStefano Zampini     if (!getRes) {
54430f0abf79SStefano Zampini       KSPNormType normtype;
54440f0abf79SStefano Zampini 
54450f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
54460f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
54470f0abf79SStefano Zampini     }
54489566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
54490f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
54509566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
545171f87433Sdalcinl     } else {
545271f87433Sdalcinl       /* KSP residual is preconditioned residual */
545371f87433Sdalcinl       /* compute true linear residual norm */
54540f0abf79SStefano Zampini       Mat J;
54550f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
54569566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
54570f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
54589566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
54599566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
54609566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
546171f87433Sdalcinl     }
546271f87433Sdalcinl   }
54633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546471f87433Sdalcinl }
546571f87433Sdalcinl 
5466d4211eb9SBarry Smith /*@
5467f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5468d4211eb9SBarry Smith 
5469420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5470d4211eb9SBarry Smith 
5471d4211eb9SBarry Smith   Input Parameter:
5472f6dfbefdSBarry Smith . snes - the `SNES` context
5473d4211eb9SBarry Smith 
5474d4211eb9SBarry Smith   Output Parameter:
5475f6dfbefdSBarry Smith . ksp - the `KSP` context
5476d4211eb9SBarry Smith 
5477dc4c0fb0SBarry Smith   Level: beginner
5478dc4c0fb0SBarry Smith 
5479d4211eb9SBarry Smith   Notes:
5480f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5481d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5482f6dfbefdSBarry Smith   `PC` contexts as well.
5483f6dfbefdSBarry Smith 
5484f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5485d4211eb9SBarry Smith 
54861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5487d4211eb9SBarry Smith @*/
5488d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5489d71ae5a4SJacob Faibussowitsch {
549071f87433Sdalcinl   PetscFunctionBegin;
5491d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54924f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5493d4211eb9SBarry Smith 
5494d4211eb9SBarry Smith   if (!snes->ksp) {
54959566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
54969566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5497d4211eb9SBarry Smith 
54985c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
54995c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5500a5c2985bSBarry Smith 
55019566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
55029566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5503d4211eb9SBarry Smith   }
5504d4211eb9SBarry Smith   *ksp = snes->ksp;
55053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
550671f87433Sdalcinl }
55076c699258SBarry Smith 
5508af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
55096c699258SBarry Smith /*@
5510f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
55116c699258SBarry Smith 
5512c3339decSBarry Smith   Logically Collective
55136c699258SBarry Smith 
55146c699258SBarry Smith   Input Parameters:
55152a808120SBarry Smith + snes - the nonlinear solver context
5516420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5517dc4c0fb0SBarry Smith 
5518dc4c0fb0SBarry Smith   Level: intermediate
55196c699258SBarry Smith 
5520f6dfbefdSBarry Smith   Note:
5521f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5522f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5523e03a659cSJed Brown   problems using the same function space.
5524e03a659cSJed Brown 
5525420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
55266c699258SBarry Smith @*/
5527d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5528d71ae5a4SJacob Faibussowitsch {
5529345fed2cSBarry Smith   KSP    ksp;
5530942e3340SBarry Smith   DMSNES sdm;
55316c699258SBarry Smith 
55326c699258SBarry Smith   PetscFunctionBegin;
55330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55342a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
55359566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5536942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
553751f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
55389566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
55399566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5540f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
55416cab3a1bSJed Brown     }
55429566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
55439566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
55446cab3a1bSJed Brown   }
55456c699258SBarry Smith   snes->dm     = dm;
5546116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5547f5af7f23SKarl Rupp 
55489566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
55499566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
55509566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5551efd4aadfSBarry Smith   if (snes->npc) {
55529566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
55539566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
55542c155ee1SBarry Smith   }
55553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55566c699258SBarry Smith }
55576c699258SBarry Smith 
55586c699258SBarry Smith /*@
5559420bcc1bSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners
55606c699258SBarry Smith 
5561f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
55626c699258SBarry Smith 
55636c699258SBarry Smith   Input Parameter:
5564420bcc1bSBarry Smith . snes - the `SNES` context
55656c699258SBarry Smith 
55666c699258SBarry Smith   Output Parameter:
5567420bcc1bSBarry Smith . dm - the `DM`
55686c699258SBarry Smith 
55696c699258SBarry Smith   Level: intermediate
55706c699258SBarry Smith 
5571420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
55726c699258SBarry Smith @*/
5573d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5574d71ae5a4SJacob Faibussowitsch {
55756c699258SBarry Smith   PetscFunctionBegin;
55760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55776cab3a1bSJed Brown   if (!snes->dm) {
55789566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5579116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
55806cab3a1bSJed Brown   }
55816c699258SBarry Smith   *dm = snes->dm;
55823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55836c699258SBarry Smith }
55840807856dSBarry Smith 
558531823bd8SMatthew G Knepley /*@
5586be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
558731823bd8SMatthew G Knepley 
5588c3339decSBarry Smith   Collective
558931823bd8SMatthew G Knepley 
559031823bd8SMatthew G Knepley   Input Parameters:
5591f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5592420bcc1bSBarry Smith - npc  - the nonlinear preconditioner object
559331823bd8SMatthew G Knepley 
5594dc4c0fb0SBarry Smith   Level: developer
5595dc4c0fb0SBarry Smith 
559631823bd8SMatthew G Knepley   Notes:
5597f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
559831823bd8SMatthew G Knepley   to configure it using the API).
559931823bd8SMatthew G Knepley 
5600f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5601f6dfbefdSBarry Smith 
5602420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
560331823bd8SMatthew G Knepley @*/
5604d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5605d71ae5a4SJacob Faibussowitsch {
560631823bd8SMatthew G Knepley   PetscFunctionBegin;
560731823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5608f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5609f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5610f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
56119566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5612f6dfbefdSBarry Smith   snes->npc = npc;
56133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
561431823bd8SMatthew G Knepley }
561531823bd8SMatthew G Knepley 
561631823bd8SMatthew G Knepley /*@
5617f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
561831823bd8SMatthew G Knepley 
5619f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
562031823bd8SMatthew G Knepley 
562131823bd8SMatthew G Knepley   Input Parameter:
5622f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
562331823bd8SMatthew G Knepley 
562431823bd8SMatthew G Knepley   Output Parameter:
5625e4094ef1SJacob Faibussowitsch . pc - preconditioner context
562631823bd8SMatthew G Knepley 
5627f6dfbefdSBarry Smith   Options Database Key:
5628f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5629b5badacbSBarry Smith 
5630dc4c0fb0SBarry Smith   Level: developer
5631dc4c0fb0SBarry Smith 
563295452b02SPatrick Sanan   Notes:
5633f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5634be95d8f1SBarry Smith 
5635f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5636f6dfbefdSBarry Smith   `SNES`
5637951fe5abSBarry Smith 
56381cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
563931823bd8SMatthew G Knepley @*/
5640d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5641d71ae5a4SJacob Faibussowitsch {
5642a64e098fSPeter Brune   const char *optionsprefix;
564331823bd8SMatthew G Knepley 
564431823bd8SMatthew G Knepley   PetscFunctionBegin;
564531823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56464f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5647efd4aadfSBarry Smith   if (!snes->npc) {
5648ec785e5bSStefano Zampini     void *ctx;
5649ec785e5bSStefano Zampini 
56509566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
56519566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
56529566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
56539566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
56549566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5655fb87a551SStefano Zampini     if (snes->ops->usercompute) {
5656fb87a551SStefano Zampini       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy));
5657fb87a551SStefano Zampini     } else {
5658ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5659ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5660fb87a551SStefano Zampini     }
56619566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
566231823bd8SMatthew G Knepley   }
5663efd4aadfSBarry Smith   *pc = snes->npc;
56643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
566531823bd8SMatthew G Knepley }
566631823bd8SMatthew G Knepley 
56673ad1a0b9SPatrick Farrell /*@
56683ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
56693ad1a0b9SPatrick Farrell 
56703ad1a0b9SPatrick Farrell   Not Collective
56713ad1a0b9SPatrick Farrell 
56723ad1a0b9SPatrick Farrell   Input Parameter:
5673f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56743ad1a0b9SPatrick Farrell 
56753ad1a0b9SPatrick Farrell   Output Parameter:
5676420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
56773ad1a0b9SPatrick Farrell 
56783ad1a0b9SPatrick Farrell   Level: developer
56793ad1a0b9SPatrick Farrell 
56801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
56813ad1a0b9SPatrick Farrell @*/
5682d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5683d71ae5a4SJacob Faibussowitsch {
56843ad1a0b9SPatrick Farrell   PetscFunctionBegin;
56853ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5686efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
56873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56883ad1a0b9SPatrick Farrell }
56893ad1a0b9SPatrick Farrell 
5690c40d0f55SPeter Brune /*@
5691420bcc1bSBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side.
5692c40d0f55SPeter Brune 
5693c3339decSBarry Smith   Logically Collective
5694c40d0f55SPeter Brune 
5695c40d0f55SPeter Brune   Input Parameter:
5696f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5697c40d0f55SPeter Brune 
5698c40d0f55SPeter Brune   Output Parameter:
5699c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5700c40d0f55SPeter Brune .vb
57012d547940SBarry Smith       PC_LEFT - left preconditioning
57022d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5703c40d0f55SPeter Brune .ve
5704c40d0f55SPeter Brune 
5705f6dfbefdSBarry Smith   Options Database Key:
570667b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5707c40d0f55SPeter Brune 
5708dc4c0fb0SBarry Smith   Level: intermediate
5709dc4c0fb0SBarry Smith 
5710f6dfbefdSBarry Smith   Note:
5711f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
57122d547940SBarry Smith 
5713420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5714c40d0f55SPeter Brune @*/
5715d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5716d71ae5a4SJacob Faibussowitsch {
5717c40d0f55SPeter Brune   PetscFunctionBegin;
5718c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5719c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5720b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
572154c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5722efd4aadfSBarry Smith   snes->npcside = side;
57233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5724c40d0f55SPeter Brune }
5725c40d0f55SPeter Brune 
5726c40d0f55SPeter Brune /*@
5727be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5728c40d0f55SPeter Brune 
5729c40d0f55SPeter Brune   Not Collective
5730c40d0f55SPeter Brune 
5731c40d0f55SPeter Brune   Input Parameter:
5732f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5733c40d0f55SPeter Brune 
5734c40d0f55SPeter Brune   Output Parameter:
5735c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5736c40d0f55SPeter Brune .vb
5737f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5738f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5739c40d0f55SPeter Brune .ve
5740c40d0f55SPeter Brune 
5741c40d0f55SPeter Brune   Level: intermediate
5742c40d0f55SPeter Brune 
5743420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5744c40d0f55SPeter Brune @*/
5745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5746d71ae5a4SJacob Faibussowitsch {
5747c40d0f55SPeter Brune   PetscFunctionBegin;
5748c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57494f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5750efd4aadfSBarry Smith   *side = snes->npcside;
57513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5752c40d0f55SPeter Brune }
5753c40d0f55SPeter Brune 
57549e764e56SPeter Brune /*@
5755420bcc1bSBarry Smith   SNESSetLineSearch - Sets the linesearch to be used for `SNES`
57569e764e56SPeter Brune 
5757c3339decSBarry Smith   Collective
57589e764e56SPeter Brune 
57599e764e56SPeter Brune   Input Parameters:
5760f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
57619e764e56SPeter Brune - linesearch - the linesearch object
57629e764e56SPeter Brune 
5763dc4c0fb0SBarry Smith   Level: developer
5764dc4c0fb0SBarry Smith 
5765f6dfbefdSBarry Smith   Note:
5766420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
57679e764e56SPeter Brune   to configure it using the API).
57689e764e56SPeter Brune 
5769420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
57709e764e56SPeter Brune @*/
5771d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5772d71ae5a4SJacob Faibussowitsch {
57739e764e56SPeter Brune   PetscFunctionBegin;
57749e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5775f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
57769e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
57779566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
57789566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5779f5af7f23SKarl Rupp 
57809e764e56SPeter Brune   snes->linesearch = linesearch;
57813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57829e764e56SPeter Brune }
57839e764e56SPeter Brune 
5784a34ceb2aSJed Brown /*@
5785420bcc1bSBarry Smith   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5786f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
57879e764e56SPeter Brune 
57889e764e56SPeter Brune   Not Collective
57899e764e56SPeter Brune 
57909e764e56SPeter Brune   Input Parameter:
5791f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57929e764e56SPeter Brune 
57939e764e56SPeter Brune   Output Parameter:
57949e764e56SPeter Brune . linesearch - linesearch context
57959e764e56SPeter Brune 
5796162e0bf5SPeter Brune   Level: beginner
57979e764e56SPeter Brune 
57981cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
57999e764e56SPeter Brune @*/
5800d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5801d71ae5a4SJacob Faibussowitsch {
58029e764e56SPeter Brune   const char *optionsprefix;
58039e764e56SPeter Brune 
58049e764e56SPeter Brune   PetscFunctionBegin;
58059e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58064f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
58079e764e56SPeter Brune   if (!snes->linesearch) {
58089566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
58099566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
58109566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
58119566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
58129566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
58139e764e56SPeter Brune   }
58149e764e56SPeter Brune   *linesearch = snes->linesearch;
58153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58169e764e56SPeter Brune }
5817