xref: /petsc/src/snes/interface/snes.c (revision 77e5a1f9fcfc1cfeb1010ff17041dc1a220acc3c)
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 
274ffeef943SBarry Smith /*@
275f6dfbefdSBarry Smith   SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
27655849f57SBarry Smith 
277c3339decSBarry Smith   Collective
27855849f57SBarry Smith 
27955849f57SBarry Smith   Input Parameters:
280e4094ef1SJacob Faibussowitsch + snes   - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
281f6dfbefdSBarry Smith            some related function before a call to `SNESLoad()`.
282f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
28355849f57SBarry Smith 
28455849f57SBarry Smith   Level: intermediate
28555849f57SBarry Smith 
286f6dfbefdSBarry Smith   Note:
287420bcc1bSBarry Smith   The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored.
28855849f57SBarry Smith 
2891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
29055849f57SBarry Smith @*/
291d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
292d71ae5a4SJacob Faibussowitsch {
29355849f57SBarry Smith   PetscBool isbinary;
294060da220SMatthew G. Knepley   PetscInt  classid;
29555849f57SBarry Smith   char      type[256];
29655849f57SBarry Smith   KSP       ksp;
2972d53ad75SBarry Smith   DM        dm;
2982d53ad75SBarry Smith   DMSNES    dmsnes;
29955849f57SBarry Smith 
30055849f57SBarry Smith   PetscFunctionBegin;
3012d53ad75SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
30255849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3045f80ce2aSJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
30555849f57SBarry Smith 
3069566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
3075f80ce2aSJacob Faibussowitsch   PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3089566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3099566063dSJacob Faibussowitsch   PetscCall(SNESSetType(snes, type));
310dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, load, viewer);
3119566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3129566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &dmsnes));
3139566063dSJacob Faibussowitsch   PetscCall(DMSNESLoad(dmsnes, viewer));
3149566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
3159566063dSJacob Faibussowitsch   PetscCall(KSPLoad(ksp, viewer));
3163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31755849f57SBarry Smith }
3186a388c36SPeter Brune 
3199804daf3SBarry Smith #include <petscdraw.h>
320e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
321e04113cfSBarry Smith   #include <petscviewersaws.h>
322bfb97211SBarry Smith #endif
3238404b7f3SBarry Smith 
324ffeef943SBarry Smith /*@
325dc4c0fb0SBarry Smith   SNESViewFromOptions - View a `SNES` based on values in the options database
326fe2efc57SMark 
327c3339decSBarry Smith   Collective
328fe2efc57SMark 
329fe2efc57SMark   Input Parameters:
330f6dfbefdSBarry Smith + A    - the `SNES` context
331dc4c0fb0SBarry Smith . obj  - Optional object that provides the options prefix for the checks
332736c3998SJose E. Roman - name - command line option
333fe2efc57SMark 
334fe2efc57SMark   Level: intermediate
335f6dfbefdSBarry Smith 
3361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
337fe2efc57SMark @*/
338d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
339d71ae5a4SJacob Faibussowitsch {
340fe2efc57SMark   PetscFunctionBegin;
341fe2efc57SMark   PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
344fe2efc57SMark }
345fe2efc57SMark 
346789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
347789d8953SBarry Smith 
348ffeef943SBarry Smith /*@
349dc4c0fb0SBarry Smith   SNESView - Prints or visualizes the `SNES` data structure.
3509b94acceSBarry Smith 
351c3339decSBarry Smith   Collective
352fee21e36SBarry Smith 
353c7afd0dbSLois Curfman McInnes   Input Parameters:
354f6dfbefdSBarry Smith + snes   - the `SNES` context
355f6dfbefdSBarry Smith - viewer - the `PetscViewer`
356c7afd0dbSLois Curfman McInnes 
3579b94acceSBarry Smith   Options Database Key:
358f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3599b94acceSBarry Smith 
360dc4c0fb0SBarry Smith   Level: beginner
361dc4c0fb0SBarry Smith 
3629b94acceSBarry Smith   Notes:
3639b94acceSBarry Smith   The available visualization contexts include
364f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
365f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
366c8a8ba5cSLois Curfman McInnes   output where only the first processor opens
367c8a8ba5cSLois Curfman McInnes   the file.  All other processors send their
368c8a8ba5cSLois Curfman McInnes   data to the first processor to print.
3699b94acceSBarry Smith 
370052bf0daSPierre Jolivet   The available formats include
371f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
372f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
373052bf0daSPierre Jolivet 
3743e081fefSLois Curfman McInnes   The user can open an alternative visualization context with
375f6dfbefdSBarry Smith   `PetscViewerASCIIOpen()` - output to a specified file.
3769b94acceSBarry Smith 
377f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
378595c91d4SBarry Smith 
3791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3809b94acceSBarry Smith @*/
381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
382d71ae5a4SJacob Faibussowitsch {
383fa9f3622SBarry Smith   SNESKSPEW     *kctx;
38494b7f48cSBarry Smith   KSP            ksp;
3857f1410a3SPeter Brune   SNESLineSearch linesearch;
38672a02f06SBarry Smith   PetscBool      iascii, isstring, isbinary, isdraw;
3872d53ad75SBarry Smith   DMSNES         dmsnes;
388e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
389536b137fSBarry Smith   PetscBool issaws;
390bfb97211SBarry Smith #endif
3919b94acceSBarry Smith 
3923a40ed3dSBarry Smith   PetscFunctionBegin;
3930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39448a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
3950700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
396c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, viewer, 2);
39774679c65SBarry Smith 
3989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
4009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
402e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
4039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
404bfb97211SBarry Smith #endif
40532077d6dSBarry Smith   if (iascii) {
406dc0571f2SMatthew G. Knepley     SNESNormSchedule normschedule;
4078404b7f3SBarry Smith     DM               dm;
4088434afd1SBarry Smith     SNESJacobianFn  *cJ;
4098404b7f3SBarry Smith     void            *ctx;
410789d8953SBarry Smith     const char      *pre = "";
411dc0571f2SMatthew G. Knepley 
4129566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
41348a46eb9SPierre Jolivet     if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  SNES has not been set up so information may be incomplete\n"));
414e7788613SBarry Smith     if (snes->ops->view) {
4159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
416dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, view, viewer);
4179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
4180ef38995SBarry Smith     }
419*77e5a1f9SBarry Smith     if (snes->max_funcs == PETSC_UNLIMITED) {
420*77e5a1f9SBarry Smith       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its));
421*77e5a1f9SBarry Smith     } else {
42263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
423*77e5a1f9SBarry Smith     }
4249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42548a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4279566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4289566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
42948a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4309b94acceSBarry Smith     if (snes->ksp_ewconv) {
431fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4329b94acceSBarry Smith       if (kctx) {
43363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4349566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4359566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4369b94acceSBarry Smith       }
4379b94acceSBarry Smith     }
438eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
440eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
44163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
442eb1f6c34SBarry Smith     }
443eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
445eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
44663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
447eb1f6c34SBarry Smith     }
4489566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4499566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
450789d8953SBarry Smith     if (snes->mf_operator) {
4519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
452789d8953SBarry Smith       pre = "Preconditioning ";
453789d8953SBarry Smith     }
4548404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4568404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
458789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
459789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
460789d8953SBarry Smith       MatFDColoring fdcoloring;
4619566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
462789d8953SBarry Smith       if (fdcoloring) {
4639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
464789d8953SBarry Smith       } else {
4659566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
466789d8953SBarry Smith       }
467996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4689566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4698404b7f3SBarry Smith     }
4700f5bd95cSBarry Smith   } else if (isstring) {
471317d6ea6SBarry Smith     const char *type;
4729566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4739566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
474dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47555849f57SBarry Smith   } else if (isbinary) {
47655849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
47755849f57SBarry Smith     MPI_Comm    comm;
47855849f57SBarry Smith     PetscMPIInt rank;
47955849f57SBarry Smith     char        type[256];
48055849f57SBarry Smith 
4819566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
483dd400576SPatrick Sanan     if (rank == 0) {
4849566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4859566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4869566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48755849f57SBarry Smith     }
488dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
48972a02f06SBarry Smith   } else if (isdraw) {
49072a02f06SBarry Smith     PetscDraw draw;
49172a02f06SBarry Smith     char      str[36];
49289fd9fafSBarry Smith     PetscReal x, y, bottom, h;
49372a02f06SBarry Smith 
4949566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4959566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4969566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4979566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
4989566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
49989fd9fafSBarry Smith     bottom = y - h;
5009566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
501dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
502e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
503536b137fSBarry Smith   } else if (issaws) {
504d45a07a7SBarry Smith     PetscMPIInt rank;
5052657e9d9SBarry Smith     const char *name;
506d45a07a7SBarry Smith 
5079566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
509dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
510d45a07a7SBarry Smith       char dir[1024];
511d45a07a7SBarry Smith 
5129566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5139566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
514792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51548a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5169566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
517792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
518f05ece33SBarry Smith     }
519bfb97211SBarry Smith #endif
52072a02f06SBarry Smith   }
52172a02f06SBarry Smith   if (snes->linesearch) {
5229566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5249566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
52619bcc07fSBarry Smith   }
527efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5299566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5314a0c5b0cSMatthew G Knepley   }
5329566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5339566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5349566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5359566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5362c155ee1SBarry Smith   if (snes->usesksp) {
5379566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5399566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5412c155ee1SBarry Smith   }
54272a02f06SBarry Smith   if (isdraw) {
54372a02f06SBarry Smith     PetscDraw draw;
5449566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5459566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5467f1410a3SPeter Brune   }
5473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5489b94acceSBarry Smith }
5499b94acceSBarry Smith 
55076b2cf59SMatthew Knepley /*
55176b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
55276b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
55376b2cf59SMatthew Knepley */
55476b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
555a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5566849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55776b2cf59SMatthew Knepley 
558ac226902SBarry Smith /*@C
559f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
56076b2cf59SMatthew Knepley 
56176b2cf59SMatthew Knepley   Not Collective
56276b2cf59SMatthew Knepley 
56376b2cf59SMatthew Knepley   Input Parameter:
56476b2cf59SMatthew Knepley . snescheck - function that checks for options
56576b2cf59SMatthew Knepley 
566420bcc1bSBarry Smith   Calling sequence of `snescheck`:
567420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
568420bcc1bSBarry Smith 
56976b2cf59SMatthew Knepley   Level: developer
57076b2cf59SMatthew Knepley 
5711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
57276b2cf59SMatthew Knepley @*/
573420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
574d71ae5a4SJacob Faibussowitsch {
57576b2cf59SMatthew Knepley   PetscFunctionBegin;
57663a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57776b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57976b2cf59SMatthew Knepley }
58076b2cf59SMatthew Knepley 
581d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
582d71ae5a4SJacob Faibussowitsch {
583aa3661deSLisandro Dalcin   Mat          J;
584895c21f2SBarry Smith   MatNullSpace nullsp;
585aa3661deSLisandro Dalcin 
586aa3661deSLisandro Dalcin   PetscFunctionBegin;
5870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
588aa3661deSLisandro Dalcin 
58998613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
59098613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5919566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
59298613b67SLisandro Dalcin   }
59398613b67SLisandro Dalcin 
5940fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
595aa3661deSLisandro Dalcin   if (version == 1) {
5969566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5979566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5989566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5991e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
6000fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
6015f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
602570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
603f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
604aa3661deSLisandro Dalcin #else
6052479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
606aa3661deSLisandro Dalcin #endif
6070fdf79fbSJacob Faibussowitsch   }
608aa3661deSLisandro Dalcin 
60901c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
610895c21f2SBarry Smith   if (snes->jacobian) {
6119566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6121baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
613895c21f2SBarry Smith   }
614895c21f2SBarry Smith 
61563a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
616d3462f78SMatthew Knepley   if (hasOperator) {
617aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
618aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6199566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
620aa3661deSLisandro Dalcin   } else {
621aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
62201c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
623b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6249566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
625172a4300SPeter Brune     } else {
626789d8953SBarry Smith       KSP       ksp;
627789d8953SBarry Smith       PC        pc;
628789d8953SBarry Smith       PetscBool match;
629789d8953SBarry Smith 
6309566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
631aa3661deSLisandro Dalcin       /* Force no preconditioner */
6329566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6339566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6342698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
635aa3661deSLisandro Dalcin       if (!match) {
6369566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6379566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
638aa3661deSLisandro Dalcin       }
639aa3661deSLisandro Dalcin     }
640789d8953SBarry Smith   }
6419566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
643aa3661deSLisandro Dalcin }
644aa3661deSLisandro Dalcin 
645d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
646d71ae5a4SJacob Faibussowitsch {
647dfe15315SJed Brown   SNES snes = (SNES)ctx;
6480298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
649dfe15315SJed Brown 
650dfe15315SJed Brown   PetscFunctionBegin;
65116ebb321SJed Brown   if (PetscLogPrintInfo) {
65216ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6539566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6549566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6559566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6569566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dmfine, "Restricting SNES solution vector from level %" PetscInt_FMT "-%" PetscInt_FMT " to level %" PetscInt_FMT "-%" PetscInt_FMT "\n", finelevel, fineclevel, coarselevel, coarseclevel));
65816ebb321SJed Brown   }
659dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
660dfe15315SJed Brown   else {
6619566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
662dfe15315SJed Brown     Xfine = Xfine_named;
663dfe15315SJed Brown   }
6649566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
665907f5c5aSLawrence Mitchell   if (Inject) {
6669566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
667907f5c5aSLawrence Mitchell   } else {
6689566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6699566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
670907f5c5aSLawrence Mitchell   }
6719566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6729566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
674dfe15315SJed Brown }
675dfe15315SJed Brown 
676d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
677d71ae5a4SJacob Faibussowitsch {
67816ebb321SJed Brown   PetscFunctionBegin;
6799566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68116ebb321SJed Brown }
68216ebb321SJed Brown 
683a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
684a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
685d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
686d71ae5a4SJacob Faibussowitsch {
687caa4e7f2SJed Brown   SNES            snes = (SNES)ctx;
68897d931d1SStefano Zampini   DMSNES          sdm;
6890298fd71SBarry Smith   Vec             X, Xnamed = NULL;
690dfe15315SJed Brown   DM              dmsave;
6914e269d77SPeter Brune   void           *ctxsave;
6928434afd1SBarry Smith   SNESJacobianFn *jac = NULL;
693caa4e7f2SJed Brown 
694caa4e7f2SJed Brown   PetscFunctionBegin;
695dfe15315SJed Brown   dmsave = snes->dm;
6969566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
697dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
69897d931d1SStefano Zampini   else {
699309d62e6SStefano Zampini     PetscBool has;
700309d62e6SStefano Zampini 
70197d931d1SStefano Zampini     /* We are on a coarser level, this vec was initialized using a DM restrict hook */
702309d62e6SStefano Zampini     PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has));
703309d62e6SStefano Zampini     PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol");
70497d931d1SStefano Zampini     PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
705dfe15315SJed Brown     X = Xnamed;
7069566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
7074e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
70848a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7094e269d77SPeter Brune   }
7104e269d77SPeter Brune 
7112b93b426SMatthew G. Knepley   /* Compute the operators */
71297d931d1SStefano Zampini   PetscCall(DMGetDMSNES(snes->dm, &sdm));
71397d931d1SStefano Zampini   if (Xnamed && sdm->ops->computefunction) {
71497d931d1SStefano Zampini     /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
71597d931d1SStefano Zampini        We make sure of this here. Disable affine shift since it is for the finest level */
71697d931d1SStefano Zampini     Vec F, saverhs = snes->vec_rhs;
71797d931d1SStefano Zampini 
71897d931d1SStefano Zampini     snes->vec_rhs = NULL;
71997d931d1SStefano Zampini     PetscCall(DMGetGlobalVector(snes->dm, &F));
72097d931d1SStefano Zampini     PetscCall(SNESComputeFunction(snes, X, F));
72197d931d1SStefano Zampini     PetscCall(DMRestoreGlobalVector(snes->dm, &F));
72297d931d1SStefano Zampini     snes->vec_rhs = saverhs;
72397d931d1SStefano Zampini     snes->nfuncs--; /* Do not log coarser level evaluations */
72497d931d1SStefano Zampini   }
72597d931d1SStefano Zampini   /* Make sure KSP DM has the Jacobian computation routine */
72697d931d1SStefano Zampini   if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7279566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
72897d931d1SStefano Zampini 
7292b93b426SMatthew G. Knepley   /* Put the previous context back */
73048a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7314e269d77SPeter Brune 
7329566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
733dfe15315SJed Brown   snes->dm = dmsave;
7343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
735caa4e7f2SJed Brown }
736caa4e7f2SJed Brown 
7376cab3a1bSJed Brown /*@
738dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7396cab3a1bSJed Brown 
7406cab3a1bSJed Brown   Collective
7416cab3a1bSJed Brown 
7424165533cSJose E. Roman   Input Parameter:
74320f4b53cSBarry Smith . snes - `SNES` object to configure
7446cab3a1bSJed Brown 
7456cab3a1bSJed Brown   Level: developer
7466cab3a1bSJed Brown 
747dc4c0fb0SBarry Smith   Note:
748dc4c0fb0SBarry Smith   If the matrices do not yet exist it attempts to create them based on options previously set for the `SNES` such as `-snes_mf`
749dc4c0fb0SBarry Smith 
75073a84a35SBarry Smith   Developer Note:
75173a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
75273a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
75373a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
75473a84a35SBarry Smith 
7551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7566cab3a1bSJed Brown @*/
757d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
758d71ae5a4SJacob Faibussowitsch {
7596cab3a1bSJed Brown   DM     dm;
760942e3340SBarry Smith   DMSNES sdm;
7616cab3a1bSJed Brown 
7626cab3a1bSJed Brown   PetscFunctionBegin;
7639566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7649566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
76573a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7666cab3a1bSJed Brown     Mat   J;
7676cab3a1bSJed Brown     void *functx;
7689566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7699566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7709566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7719566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7729566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7739566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
774caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7756cab3a1bSJed Brown     Mat J, B;
7769566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7779566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7789566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7799566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
78006f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7819566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7829566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7839566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
784caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7851ba9b98eSMatthew G. Knepley     PetscDS   prob;
7866cab3a1bSJed Brown     Mat       J, B;
7871ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7881ba9b98eSMatthew G. Knepley 
7896cab3a1bSJed Brown     J = snes->jacobian;
7909566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7919566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7929566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7939566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7949566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7959566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7986cab3a1bSJed Brown   }
799caa4e7f2SJed Brown   {
800caa4e7f2SJed Brown     KSP ksp;
8019566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
8029566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
8039566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
804caa4e7f2SJed Brown   }
8053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8066cab3a1bSJed Brown }
8076cab3a1bSJed Brown 
808d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
809d71ae5a4SJacob Faibussowitsch {
8105e7c47f3SMatthew G. Knepley   PetscInt i;
8115e7c47f3SMatthew G. Knepley 
8125e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8133ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
8145e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
8155e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
8165e7c47f3SMatthew G. Knepley     PetscDraw             draw;
8175e7c47f3SMatthew G. Knepley     PetscReal             lpause;
8185e7c47f3SMatthew G. Knepley 
8195e7c47f3SMatthew G. Knepley     if (!vf) continue;
8205e7c47f3SMatthew G. Knepley     if (vf->lg) {
8215e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
8225e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
8239566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
8249566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8259566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8269566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8279566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8285e7c47f3SMatthew G. Knepley     } else {
8295e7c47f3SMatthew G. Knepley       PetscBool isdraw;
8305e7c47f3SMatthew G. Knepley 
8315e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
8325e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
8339566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
8345e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
8359566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
8369566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8379566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8389566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8399566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8405e7c47f3SMatthew G. Knepley     }
8415e7c47f3SMatthew G. Knepley   }
8423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8435e7c47f3SMatthew G. Knepley }
8445e7c47f3SMatthew G. Knepley 
845fde5950dSBarry Smith /*@C
846fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
847fde5950dSBarry Smith 
848c3339decSBarry Smith   Collective
849fde5950dSBarry Smith 
850fde5950dSBarry Smith   Input Parameters:
851dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
852fde5950dSBarry Smith . name         - the monitor type one is seeking
853fde5950dSBarry Smith . help         - message indicating what monitoring is done
854fde5950dSBarry Smith . manual       - manual page for the monitor
855fde5950dSBarry Smith . monitor      - the monitor function
856f6dfbefdSBarry Smith - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `SNES` or `PetscViewer` objects
857fde5950dSBarry Smith 
858420bcc1bSBarry Smith   Calling sequence of `monitor`:
859420bcc1bSBarry Smith + snes - the nonlinear solver context
860420bcc1bSBarry Smith . it   - the current iteration
861420bcc1bSBarry Smith . r    - the current function norm
862420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
863420bcc1bSBarry Smith 
864420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
865420bcc1bSBarry Smith + snes - the nonlinear solver context
866420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
867420bcc1bSBarry Smith 
868f6dfbefdSBarry Smith   Options Database Key:
869f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
870f6dfbefdSBarry Smith 
871f6dfbefdSBarry Smith   Level: advanced
872fde5950dSBarry Smith 
873648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
874db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
875e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
876db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
877c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
878db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
879db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
880fde5950dSBarry Smith @*/
881420bcc1bSBarry Smith PetscErrorCode SNESMonitorSetFromOptions(SNES snes, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNES snes, PetscInt it, PetscReal r, PetscViewerAndFormat *vf), PetscErrorCode (*monitorsetup)(SNES snes, PetscViewerAndFormat *vf))
882d71ae5a4SJacob Faibussowitsch {
883fde5950dSBarry Smith   PetscViewer       viewer;
884fde5950dSBarry Smith   PetscViewerFormat format;
885fde5950dSBarry Smith   PetscBool         flg;
886fde5950dSBarry Smith 
887fde5950dSBarry Smith   PetscFunctionBegin;
888648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
889fde5950dSBarry Smith   if (flg) {
890d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8919566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
892648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
8931baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8949566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
895fde5950dSBarry Smith   }
8963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
897fde5950dSBarry Smith }
898fde5950dSBarry Smith 
899a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
900d71ae5a4SJacob Faibussowitsch {
901a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
902a4598233SStefano Zampini 
9030f0abf79SStefano Zampini   PetscFunctionBegin;
9040f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
905a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
906a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
907a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
908a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
909a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
910a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
9110f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
912a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
9130f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
9140f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
9150f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
9160f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
9170f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
9180f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
9190f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
9200f0abf79SStefano Zampini   PetscOptionsEnd();
9213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9220f0abf79SStefano Zampini }
9230f0abf79SStefano Zampini 
9249b94acceSBarry Smith /*@
925f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9269b94acceSBarry Smith 
927c3339decSBarry Smith   Collective
928c7afd0dbSLois Curfman McInnes 
9299b94acceSBarry Smith   Input Parameter:
930f6dfbefdSBarry Smith . snes - the `SNES` context
9319b94acceSBarry Smith 
93236851e7fSLois Curfman McInnes   Options Database Keys:
933f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
934b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
935*77e5a1f9SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
936*77e5a1f9SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
937e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
938b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
939b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
940*77e5a1f9SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
9414839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
942ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
943a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9443d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
945e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9463d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
9474a221d59SStefano Zampini . -snes_tr_tol <trtol>                                                         - trust region tolerance
948ceaaa498SBarry 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.
949fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
950fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
951fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
952fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9534619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
954459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9555e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
956e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
957e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
958ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
959b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
960ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
961e62ac41dSBarry 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.
962e62ac41dSBarry 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.
96382738288SBarry Smith 
964f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
965fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9664b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
96736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
96836851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
96936851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
97036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
97136851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
97236851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
97382738288SBarry Smith 
974dc4c0fb0SBarry Smith   Level: beginner
975dc4c0fb0SBarry Smith 
97611ca99fdSLois Curfman McInnes   Notes:
977ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
978ec5066bdSBarry Smith 
979420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
980420bcc1bSBarry Smith   and computing explicitly with
981f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
98283e2fdc7SBarry Smith 
983420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9849b94acceSBarry Smith @*/
985d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
986d71ae5a4SJacob Faibussowitsch {
9878afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
988*77e5a1f9SBarry Smith   PetscInt    i, indx, lag, grids, max_its, max_funcs;
98904d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
990649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
99185385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9920f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
993c40d0f55SPeter Brune   PCSide      pcside;
994a64e098fSPeter Brune   const char *optionsprefix;
995*77e5a1f9SBarry Smith   PetscReal   rtol, abstol, stol;
9969b94acceSBarry Smith 
9973a40ed3dSBarry Smith   PetscFunctionBegin;
9980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9999566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
1000d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
1001639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
10029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
1003d64ed03dSBarry Smith   if (flg) {
10049566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
10057adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
10069566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
1007d64ed03dSBarry Smith   }
1008186905e3SBarry Smith 
1009*77e5a1f9SBarry Smith   abstol    = snes->abstol;
1010*77e5a1f9SBarry Smith   rtol      = snes->rtol;
1011*77e5a1f9SBarry Smith   stol      = snes->stol;
1012*77e5a1f9SBarry Smith   max_its   = snes->max_its;
1013*77e5a1f9SBarry Smith   max_funcs = snes->max_funcs;
1014*77e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL));
1015*77e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL));
1016*77e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL));
1017*77e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL));
1018*77e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL));
1019*77e5a1f9SBarry Smith   PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs));
1020*77e5a1f9SBarry Smith 
1021*77e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg));
1022*77e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol));
1023*77e5a1f9SBarry Smith 
1024*77e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg));
1025*77e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures));
1026*77e5a1f9SBarry Smith 
1027*77e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg));
1028*77e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures));
1029*77e5a1f9SBarry Smith 
10309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
103385385478SLisandro Dalcin 
10349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1035a8054027SBarry Smith   if (flg) {
10365f80ce2aSJacob 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");
10379566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1038a8054027SBarry Smith   }
10399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10401baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1042e35cf81dSBarry Smith   if (flg) {
10435f80ce2aSJacob 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");
10449566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1045e35cf81dSBarry Smith   }
10469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10471baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
104837ec4e1aSPeter Brune 
10499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10501baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1051a8054027SBarry Smith 
1052400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
105385385478SLisandro Dalcin   if (flg) {
105485385478SLisandro Dalcin     switch (indx) {
1055d71ae5a4SJacob Faibussowitsch     case 0:
1056d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1057d71ae5a4SJacob Faibussowitsch       break;
1058d71ae5a4SJacob Faibussowitsch     case 1:
1059d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1060d71ae5a4SJacob Faibussowitsch       break;
1061d71ae5a4SJacob Faibussowitsch     case 2:
1062d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1063d71ae5a4SJacob Faibussowitsch       break;
106485385478SLisandro Dalcin     }
106585385478SLisandro Dalcin   }
106685385478SLisandro Dalcin 
10679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10689566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1069fdacfa88SPeter Brune 
10709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10719566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1072186905e3SBarry Smith 
107385385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
107485385478SLisandro Dalcin 
10759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1076186905e3SBarry Smith 
10770f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10780f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1079a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1080186905e3SBarry Smith 
108190d69ab7SBarry Smith   flg = PETSC_FALSE;
10829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10839566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1084eabae89aSBarry Smith 
10859566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10869566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10879566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1088eabae89aSBarry Smith 
10899566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10909566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10919566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10929566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10939566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10949566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10959566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10972db13446SMatthew G. Knepley 
10989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10999566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
11005180491cSLisandro Dalcin 
110190d69ab7SBarry Smith   flg = PETSC_FALSE;
11029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1103459f5d12SBarry Smith   if (flg) {
1104459f5d12SBarry Smith     PetscViewer ctx;
1105e24b481bSBarry Smith 
11069566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
11079566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1108459f5d12SBarry Smith   }
11092e7541e6SPeter Brune 
1110648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1111648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
111290d69ab7SBarry Smith   flg = PETSC_FALSE;
11139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
11149566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1115c4421ceaSFande Kong 
1116c4421ceaSFande Kong   flg = PETSC_FALSE;
11179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
11184b27c08aSLois Curfman McInnes   if (flg) {
11196cab3a1bSJed Brown     void *functx;
1120b1f624c7SBarry Smith     DM    dm;
11219566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1122800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11239566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
11249566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
11259566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11269b94acceSBarry Smith   }
1127639f9d9dSBarry Smith 
112844848bc4SPeter Brune   flg = PETSC_FALSE;
11299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11301baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
113197584545SPeter Brune 
113297584545SPeter Brune   flg = PETSC_FALSE;
11339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
113444848bc4SPeter Brune   if (flg) {
1135c52e227fSPeter Brune     DM dm;
11369566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1137800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11389566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11399566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
114044848bc4SPeter Brune   }
114144848bc4SPeter Brune 
1142aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1144d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1145a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1146d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1147a8248277SBarry Smith   }
1148aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1150d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1152d28543b3SPeter Brune 
1153c40d0f55SPeter Brune   flg = PETSC_FALSE;
11549566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11569566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1157c40d0f55SPeter Brune 
1158e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11598a70d858SHong Zhang   /*
11608a70d858SHong Zhang     Publish convergence information using SAWs
11618a70d858SHong Zhang   */
11628a70d858SHong Zhang   flg = PETSC_FALSE;
11639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11648a70d858SHong Zhang   if (flg) {
11658a70d858SHong Zhang     void *ctx;
11669566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11679566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11688a70d858SHong Zhang   }
11698a70d858SHong Zhang #endif
11708a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1171b90c6cbeSBarry Smith   {
1172b90c6cbeSBarry Smith     PetscBool set;
1173b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11749566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11751baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1176b90c6cbeSBarry Smith   }
1177b90c6cbeSBarry Smith #endif
1178b90c6cbeSBarry Smith 
117948a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
118076b2cf59SMatthew Knepley 
1181dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11825d973c19SBarry Smith 
11835d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1184dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1185d0609cedSBarry Smith   PetscOptionsEnd();
11864bbc92c1SBarry Smith 
1187d8d34be6SBarry Smith   if (snes->linesearch) {
11889566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11899566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1190d8d34be6SBarry Smith   }
11919e764e56SPeter Brune 
11926aa5e7e9SBarry Smith   if (snes->usesksp) {
11939566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11949566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11959566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11966aa5e7e9SBarry Smith   }
11976991f827SBarry Smith 
1198b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11999566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
12009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
120148a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
12021baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1203b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
12043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1205b3cd9a81SMatthew G. Knepley }
1206b3cd9a81SMatthew G. Knepley 
1207b3cd9a81SMatthew G. Knepley /*@
1208420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1209b3cd9a81SMatthew G. Knepley 
1210c3339decSBarry Smith   Collective
1211b3cd9a81SMatthew G. Knepley 
1212b3cd9a81SMatthew G. Knepley   Input Parameter:
1213f6dfbefdSBarry Smith . snes - the `SNES` context
1214b3cd9a81SMatthew G. Knepley 
1215420bcc1bSBarry Smith   Level: advanced
1216b3cd9a81SMatthew G. Knepley 
12171cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1218b3cd9a81SMatthew G. Knepley @*/
1219d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1220d71ae5a4SJacob Faibussowitsch {
1221b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
12229566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12249b94acceSBarry Smith }
12259b94acceSBarry Smith 
1226bb9467b5SJed Brown /*@C
1227d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1228d25893d9SBarry Smith   the nonlinear solvers.
1229d25893d9SBarry Smith 
1230dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1231d25893d9SBarry Smith 
1232d25893d9SBarry Smith   Input Parameters:
1233f6dfbefdSBarry Smith + snes    - the `SNES` context
1234d25893d9SBarry Smith . compute - function to compute the context
1235d25893d9SBarry Smith - destroy - function to destroy the context
1236d25893d9SBarry Smith 
1237420bcc1bSBarry Smith   Calling sequence of `compute`:
1238420bcc1bSBarry Smith + snes - the `SNES` context
1239420bcc1bSBarry Smith - ctx  - context to be computed
1240420bcc1bSBarry Smith 
1241420bcc1bSBarry Smith   Calling sequence of `destroy`:
1242420bcc1bSBarry Smith . ctx - context to be computed by `compute()`
1243420bcc1bSBarry Smith 
1244d25893d9SBarry Smith   Level: intermediate
1245d25893d9SBarry Smith 
1246f6dfbefdSBarry Smith   Note:
1247f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1248f6dfbefdSBarry Smith 
1249f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1250f6dfbefdSBarry Smith 
125142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`
1252d25893d9SBarry Smith @*/
1253420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx))
1254d71ae5a4SJacob Faibussowitsch {
1255d25893d9SBarry Smith   PetscFunctionBegin;
1256d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1257d25893d9SBarry Smith   snes->ops->usercompute = compute;
1258d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
12593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1260d25893d9SBarry Smith }
1261a847f771SSatish Balay 
1262b07ff414SBarry Smith /*@
1263f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12649b94acceSBarry Smith 
1265c3339decSBarry Smith   Logically Collective
1266fee21e36SBarry Smith 
1267c7afd0dbSLois Curfman McInnes   Input Parameters:
1268f6dfbefdSBarry Smith + snes - the `SNES` context
1269c7afd0dbSLois Curfman McInnes - usrP - optional user context
1270c7afd0dbSLois Curfman McInnes 
127136851e7fSLois Curfman McInnes   Level: intermediate
127236851e7fSLois Curfman McInnes 
1273f6dfbefdSBarry Smith   Notes:
1274f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1275f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1276f6dfbefdSBarry Smith 
1277f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1278f6dfbefdSBarry Smith 
1279420bcc1bSBarry Smith   Fortran Note:
1280dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1281420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1282daf670e6SBarry Smith 
12831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12849b94acceSBarry Smith @*/
1285d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1286d71ae5a4SJacob Faibussowitsch {
1287b07ff414SBarry Smith   KSP ksp;
12881b2093e4SBarry Smith 
12893a40ed3dSBarry Smith   PetscFunctionBegin;
12900700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12919566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12929566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12939b94acceSBarry Smith   snes->user = usrP;
12943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12959b94acceSBarry Smith }
129674679c65SBarry Smith 
1297b07ff414SBarry Smith /*@
12989b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1299420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
13009b94acceSBarry Smith 
1301c7afd0dbSLois Curfman McInnes   Not Collective
1302c7afd0dbSLois Curfman McInnes 
13039b94acceSBarry Smith   Input Parameter:
1304f6dfbefdSBarry Smith . snes - `SNES` context
13059b94acceSBarry Smith 
13069b94acceSBarry Smith   Output Parameter:
13079b94acceSBarry Smith . usrP - user context
13089b94acceSBarry Smith 
130936851e7fSLois Curfman McInnes   Level: intermediate
131036851e7fSLois Curfman McInnes 
1311420bcc1bSBarry Smith   Fortran Note:
1312dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1313420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1314dc4c0fb0SBarry Smith 
1315420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13169b94acceSBarry Smith @*/
1317d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1318d71ae5a4SJacob Faibussowitsch {
13193a40ed3dSBarry Smith   PetscFunctionBegin;
13200700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1321e71120c6SJed Brown   *(void **)usrP = snes->user;
13223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13239b94acceSBarry Smith }
132474679c65SBarry Smith 
13259b94acceSBarry Smith /*@
1326420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13273565c898SBarry Smith 
1328dc4c0fb0SBarry Smith   Logically Collective
13293565c898SBarry Smith 
13303565c898SBarry Smith   Input Parameters:
1331f6dfbefdSBarry Smith + snes        - `SNES` context
1332f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1333f6dfbefdSBarry 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
1334420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13353565c898SBarry Smith 
1336f6dfbefdSBarry Smith   Options Database Keys:
133701c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1338f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1339ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1340ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13413565c898SBarry Smith 
13423565c898SBarry Smith   Level: intermediate
13433565c898SBarry Smith 
1344f6dfbefdSBarry Smith   Note:
1345420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1346420bcc1bSBarry Smith   and computing explicitly with
1347f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1348ec5066bdSBarry Smith 
1349420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13503565c898SBarry Smith @*/
1351d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1352d71ae5a4SJacob Faibussowitsch {
13533565c898SBarry Smith   PetscFunctionBegin;
13543565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
135588b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
135688b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13574ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13583565c898SBarry Smith   snes->mf_operator = mf_operator;
13593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13603565c898SBarry Smith }
13613565c898SBarry Smith 
13623565c898SBarry Smith /*@
1363dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13643565c898SBarry Smith 
1365420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13663565c898SBarry Smith 
13673565c898SBarry Smith   Input Parameter:
1368f6dfbefdSBarry Smith . snes - `SNES` context
13693565c898SBarry Smith 
13703565c898SBarry Smith   Output Parameters:
1371f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1372f6dfbefdSBarry 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
13733565c898SBarry Smith 
13743565c898SBarry Smith   Level: intermediate
13753565c898SBarry Smith 
13761cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13773565c898SBarry Smith @*/
1378d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1379d71ae5a4SJacob Faibussowitsch {
13803565c898SBarry Smith   PetscFunctionBegin;
13813565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13823565c898SBarry Smith   if (mf) *mf = snes->mf;
13833565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13853565c898SBarry Smith }
13863565c898SBarry Smith 
13873565c898SBarry Smith /*@
1388420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13899b94acceSBarry Smith 
1390c7afd0dbSLois Curfman McInnes   Not Collective
1391c7afd0dbSLois Curfman McInnes 
13929b94acceSBarry Smith   Input Parameter:
1393f6dfbefdSBarry Smith . snes - `SNES` context
13949b94acceSBarry Smith 
13959b94acceSBarry Smith   Output Parameter:
13969b94acceSBarry Smith . iter - iteration number
13979b94acceSBarry Smith 
1398dc4c0fb0SBarry Smith   Level: intermediate
1399dc4c0fb0SBarry Smith 
1400c8228a4eSBarry Smith   Notes:
1401c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1402c8228a4eSBarry Smith 
1403c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1404f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
140508405cd6SLois Curfman McInnes .vb
140608405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
140708405cd6SLois Curfman McInnes       if (!(it % 2)) {
140808405cd6SLois Curfman McInnes         [compute Jacobian here]
140908405cd6SLois Curfman McInnes       }
141008405cd6SLois Curfman McInnes .ve
1411f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1412f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1413c8228a4eSBarry Smith 
1414f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1415c04deec6SBarry Smith 
1416420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14179b94acceSBarry Smith @*/
1418d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1419d71ae5a4SJacob Faibussowitsch {
14203a40ed3dSBarry Smith   PetscFunctionBegin;
14210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14224f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14239b94acceSBarry Smith   *iter = snes->iter;
14243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14259b94acceSBarry Smith }
142674679c65SBarry Smith 
1427360c497dSPeter Brune /*@
1428360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1429360c497dSPeter Brune 
1430360c497dSPeter Brune   Not Collective
1431360c497dSPeter Brune 
1432d8d19677SJose E. Roman   Input Parameters:
1433f6dfbefdSBarry Smith + snes - `SNES` context
1434a2b725a8SWilliam Gropp - iter - iteration number
1435360c497dSPeter Brune 
1436360c497dSPeter Brune   Level: developer
1437360c497dSPeter Brune 
1438420bcc1bSBarry Smith   Note:
1439420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1440420bcc1bSBarry Smith 
14411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1442360c497dSPeter Brune @*/
1443d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1444d71ae5a4SJacob Faibussowitsch {
1445360c497dSPeter Brune   PetscFunctionBegin;
1446360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14479566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1448360c497dSPeter Brune   snes->iter = iter;
14499566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1451360c497dSPeter Brune }
1452360c497dSPeter Brune 
14539b94acceSBarry Smith /*@
1454b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1455420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14569b94acceSBarry Smith 
1457c7afd0dbSLois Curfman McInnes   Not Collective
1458c7afd0dbSLois Curfman McInnes 
14599b94acceSBarry Smith   Input Parameter:
1460f6dfbefdSBarry Smith . snes - `SNES` context
14619b94acceSBarry Smith 
14629b94acceSBarry Smith   Output Parameter:
14639b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14649b94acceSBarry Smith 
1465dc4c0fb0SBarry Smith   Level: intermediate
1466dc4c0fb0SBarry Smith 
1467f6dfbefdSBarry Smith   Note:
1468f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1469c96a6f78SLois Curfman McInnes 
14701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1471db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14729b94acceSBarry Smith @*/
1473d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1474d71ae5a4SJacob Faibussowitsch {
14753a40ed3dSBarry Smith   PetscFunctionBegin;
14760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14774f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
147850ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
148050ffb88aSMatthew Knepley }
148150ffb88aSMatthew Knepley 
148250ffb88aSMatthew Knepley /*@
1483b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1484420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
148550ffb88aSMatthew Knepley 
148650ffb88aSMatthew Knepley   Not Collective
148750ffb88aSMatthew Knepley 
148850ffb88aSMatthew Knepley   Input Parameters:
1489f6dfbefdSBarry Smith + snes     - `SNES` context
1490*77e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
149150ffb88aSMatthew Knepley 
1492420bcc1bSBarry Smith   Options Database Key:
1493420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1494420bcc1bSBarry Smith 
149550ffb88aSMatthew Knepley   Level: intermediate
149650ffb88aSMatthew Knepley 
1497420bcc1bSBarry Smith   Developer Note:
1498420bcc1bSBarry Smith   The options database key is wrong for this function name
1499420bcc1bSBarry Smith 
15001cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1501db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
150250ffb88aSMatthew Knepley @*/
1503d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1504d71ae5a4SJacob Faibussowitsch {
150550ffb88aSMatthew Knepley   PetscFunctionBegin;
15060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1507*77e5a1f9SBarry Smith 
1508*77e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
1509*77e5a1f9SBarry Smith     snes->maxFailures = PETSC_MAX_INT;
1510*77e5a1f9SBarry Smith   } else {
1511*77e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
151250ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
1513*77e5a1f9SBarry Smith   }
15143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151550ffb88aSMatthew Knepley }
151650ffb88aSMatthew Knepley 
151750ffb88aSMatthew Knepley /*@
1518b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1519420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
152050ffb88aSMatthew Knepley 
152150ffb88aSMatthew Knepley   Not Collective
152250ffb88aSMatthew Knepley 
152350ffb88aSMatthew Knepley   Input Parameter:
152420f4b53cSBarry Smith . snes - `SNES` context
152550ffb88aSMatthew Knepley 
152650ffb88aSMatthew Knepley   Output Parameter:
152750ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
152850ffb88aSMatthew Knepley 
152950ffb88aSMatthew Knepley   Level: intermediate
153050ffb88aSMatthew Knepley 
15311cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1532db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
153350ffb88aSMatthew Knepley @*/
1534d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1535d71ae5a4SJacob Faibussowitsch {
153650ffb88aSMatthew Knepley   PetscFunctionBegin;
15370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15384f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
153950ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15419b94acceSBarry Smith }
1542a847f771SSatish Balay 
15432541af92SBarry Smith /*@
15442541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1545420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15462541af92SBarry Smith 
15472541af92SBarry Smith   Not Collective
15482541af92SBarry Smith 
15492541af92SBarry Smith   Input Parameter:
1550f6dfbefdSBarry Smith . snes - `SNES` context
15512541af92SBarry Smith 
15522541af92SBarry Smith   Output Parameter:
15532541af92SBarry Smith . nfuncs - number of evaluations
15542541af92SBarry Smith 
15552541af92SBarry Smith   Level: intermediate
15562541af92SBarry Smith 
1557f6dfbefdSBarry Smith   Note:
1558f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1559971e163fSPeter Brune 
15601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15612541af92SBarry Smith @*/
1562d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1563d71ae5a4SJacob Faibussowitsch {
15642541af92SBarry Smith   PetscFunctionBegin;
15650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15664f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15672541af92SBarry Smith   *nfuncs = snes->nfuncs;
15683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15692541af92SBarry Smith }
15702541af92SBarry Smith 
15713d4c4710SBarry Smith /*@
15723d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1573420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15743d4c4710SBarry Smith 
15753d4c4710SBarry Smith   Not Collective
15763d4c4710SBarry Smith 
15773d4c4710SBarry Smith   Input Parameter:
1578f6dfbefdSBarry Smith . snes - `SNES` context
15793d4c4710SBarry Smith 
15803d4c4710SBarry Smith   Output Parameter:
15813d4c4710SBarry Smith . nfails - number of failed solves
15823d4c4710SBarry Smith 
1583f6dfbefdSBarry Smith   Options Database Key:
15849d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15859d85da0cSMatthew G. Knepley 
1586f6dfbefdSBarry Smith   Level: intermediate
1587f6dfbefdSBarry Smith 
1588f6dfbefdSBarry Smith   Note:
1589f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15903d4c4710SBarry Smith 
15911cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15923d4c4710SBarry Smith @*/
1593d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1594d71ae5a4SJacob Faibussowitsch {
15953d4c4710SBarry Smith   PetscFunctionBegin;
15960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15974f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15983d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16003d4c4710SBarry Smith }
16013d4c4710SBarry Smith 
16023d4c4710SBarry Smith /*@
16033d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1604f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
16053d4c4710SBarry Smith 
1606c3339decSBarry Smith   Logically Collective
16073d4c4710SBarry Smith 
16083d4c4710SBarry Smith   Input Parameters:
1609f6dfbefdSBarry Smith + snes     - `SNES` context
1610*77e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16113d4c4710SBarry Smith 
1612f6dfbefdSBarry Smith   Options Database Key:
16139d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16149d85da0cSMatthew G. Knepley 
1615dc4c0fb0SBarry Smith   Level: intermediate
1616dc4c0fb0SBarry Smith 
1617f6dfbefdSBarry Smith   Note:
1618f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16193d4c4710SBarry Smith 
1620420bcc1bSBarry Smith   Developer Note:
1621420bcc1bSBarry Smith   The options database key is wrong for this function name
1622420bcc1bSBarry Smith 
16231cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16243d4c4710SBarry Smith @*/
1625d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1626d71ae5a4SJacob Faibussowitsch {
16273d4c4710SBarry Smith   PetscFunctionBegin;
16280700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1629c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
1630*77e5a1f9SBarry Smith 
1631*77e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
1632*77e5a1f9SBarry Smith     snes->maxLinearSolveFailures = PETSC_MAX_INT;
1633*77e5a1f9SBarry Smith   } else {
1634*77e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16353d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
1636*77e5a1f9SBarry Smith   }
16373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16383d4c4710SBarry Smith }
16393d4c4710SBarry Smith 
16403d4c4710SBarry Smith /*@
16413d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1642f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16433d4c4710SBarry Smith 
16443d4c4710SBarry Smith   Not Collective
16453d4c4710SBarry Smith 
16463d4c4710SBarry Smith   Input Parameter:
1647f6dfbefdSBarry Smith . snes - `SNES` context
16483d4c4710SBarry Smith 
16493d4c4710SBarry Smith   Output Parameter:
16503d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16513d4c4710SBarry Smith 
16523d4c4710SBarry Smith   Level: intermediate
16533d4c4710SBarry Smith 
1654f6dfbefdSBarry Smith   Note:
1655f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16563d4c4710SBarry Smith 
16571cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16583d4c4710SBarry Smith @*/
1659d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1660d71ae5a4SJacob Faibussowitsch {
16613d4c4710SBarry Smith   PetscFunctionBegin;
16620700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16634f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16643d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16663d4c4710SBarry Smith }
16673d4c4710SBarry Smith 
1668c96a6f78SLois Curfman McInnes /*@
1669b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1670420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1671c96a6f78SLois Curfman McInnes 
1672c7afd0dbSLois Curfman McInnes   Not Collective
1673c7afd0dbSLois Curfman McInnes 
1674c96a6f78SLois Curfman McInnes   Input Parameter:
1675f6dfbefdSBarry Smith . snes - `SNES` context
1676c96a6f78SLois Curfman McInnes 
1677c96a6f78SLois Curfman McInnes   Output Parameter:
1678c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1679c96a6f78SLois Curfman McInnes 
1680dc4c0fb0SBarry Smith   Level: intermediate
1681dc4c0fb0SBarry Smith 
1682c96a6f78SLois Curfman McInnes   Notes:
1683f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1684c96a6f78SLois Curfman McInnes 
1685f6dfbefdSBarry 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
1686f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1687010be392SBarry Smith 
16881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1689c96a6f78SLois Curfman McInnes @*/
1690d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1691d71ae5a4SJacob Faibussowitsch {
16923a40ed3dSBarry Smith   PetscFunctionBegin;
16930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16944f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1695c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1697c96a6f78SLois Curfman McInnes }
1698c96a6f78SLois Curfman McInnes 
1699971e163fSPeter Brune /*@
1700971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1701f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1702971e163fSPeter Brune 
1703c3339decSBarry Smith   Logically Collective
1704971e163fSPeter Brune 
1705d8d19677SJose E. Roman   Input Parameters:
1706f6dfbefdSBarry Smith + snes  - `SNES` context
1707f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1708971e163fSPeter Brune 
1709971e163fSPeter Brune   Level: developer
1710971e163fSPeter Brune 
17111cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1712971e163fSPeter Brune @*/
1713d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1714d71ae5a4SJacob Faibussowitsch {
1715971e163fSPeter Brune   PetscFunctionBegin;
1716971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1717971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1718971e163fSPeter Brune   snes->counters_reset = reset;
17193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1720971e163fSPeter Brune }
1721971e163fSPeter Brune 
17222999313aSBarry Smith /*@
1723f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17242999313aSBarry Smith 
1725420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17262999313aSBarry Smith 
17272999313aSBarry Smith   Input Parameters:
1728f6dfbefdSBarry Smith + snes - the `SNES` context
1729f6dfbefdSBarry Smith - ksp  - the `KSP` context
17302999313aSBarry Smith 
1731dc4c0fb0SBarry Smith   Level: developer
1732dc4c0fb0SBarry Smith 
17332999313aSBarry Smith   Notes:
1734f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17352999313aSBarry Smith   so this routine is rarely needed.
17362999313aSBarry Smith 
1737f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1738420bcc1bSBarry Smith   decreased by one when this is called.
17392999313aSBarry Smith 
174042747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17412999313aSBarry Smith @*/
1742d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1743d71ae5a4SJacob Faibussowitsch {
17442999313aSBarry Smith   PetscFunctionBegin;
17450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17460700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17472999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17489566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17499566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17502999313aSBarry Smith   snes->ksp = ksp;
17513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17522999313aSBarry Smith }
17532999313aSBarry Smith 
175452baeb72SSatish Balay /*@
1755*77e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
1756*77e5a1f9SBarry Smith   currently contain default values
1757*77e5a1f9SBarry Smith 
1758*77e5a1f9SBarry Smith   Collective
1759*77e5a1f9SBarry Smith 
1760*77e5a1f9SBarry Smith   Input Parameter:
1761*77e5a1f9SBarry Smith . snes - the `SNES` object
1762*77e5a1f9SBarry Smith 
1763*77e5a1f9SBarry Smith   Level: developer
1764*77e5a1f9SBarry Smith 
1765*77e5a1f9SBarry Smith   Developer Note:
1766*77e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
1767*77e5a1f9SBarry Smith 
1768*77e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
1769*77e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
1770*77e5a1f9SBarry Smith @*/
1771*77e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
1772*77e5a1f9SBarry Smith {
1773*77e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
1774*77e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
1775*77e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
1776*77e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
1777*77e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
1778*77e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, deltatol, PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12);
1779*77e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
1780*77e5a1f9SBarry Smith   return PETSC_SUCCESS;
1781*77e5a1f9SBarry Smith }
1782*77e5a1f9SBarry Smith 
1783*77e5a1f9SBarry Smith /*@
1784dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
17859b94acceSBarry Smith 
1786d083f849SBarry Smith   Collective
1787c7afd0dbSLois Curfman McInnes 
1788f6dfbefdSBarry Smith   Input Parameter:
1789906ed7ccSBarry Smith . comm - MPI communicator
17909b94acceSBarry Smith 
17919b94acceSBarry Smith   Output Parameter:
179220f4b53cSBarry Smith . outsnes - the new `SNES` context
17939b94acceSBarry Smith 
1794c7afd0dbSLois Curfman McInnes   Options Database Keys:
1795dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1796dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1797dc4c0fb0SBarry Smith                       as set by `SNESSetJacobian()`
1798dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1799c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1800c1f60f51SBarry Smith 
180136851e7fSLois Curfman McInnes   Level: beginner
180236851e7fSLois Curfman McInnes 
180395452b02SPatrick Sanan   Developer Notes:
1804f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1805efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1806f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1807f6dfbefdSBarry Smith   in `SNESView()`.
1808efd4aadfSBarry Smith 
1809f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1810f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1811f6dfbefdSBarry Smith 
1812dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1813efd4aadfSBarry Smith 
1814e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18159b94acceSBarry Smith @*/
1816d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1817d71ae5a4SJacob Faibussowitsch {
18189b94acceSBarry Smith   SNES       snes;
1819fa9f3622SBarry Smith   SNESKSPEW *kctx;
182037fcc0dbSBarry Smith 
18213a40ed3dSBarry Smith   PetscFunctionBegin;
18224f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18239566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18248ba1e511SMatthew Knepley 
18259566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18268d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18272c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18289b94acceSBarry Smith   snes->norm           = 0.0;
1829c1e67a49SFande Kong   snes->xnorm          = 0.0;
1830c1e67a49SFande Kong   snes->ynorm          = 0.0;
1831365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18326c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1833b4874afaSBarry Smith   snes->ttol           = 0.0;
1834*77e5a1f9SBarry Smith 
1835e37c518bSBarry Smith   snes->rnorm0               = 0;
18369b94acceSBarry Smith   snes->nfuncs               = 0;
183750ffb88aSMatthew Knepley   snes->numFailures          = 0;
183850ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18397a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1840e35cf81dSBarry Smith   snes->lagjacobian          = 1;
184137ec4e1aSPeter Brune   snes->jac_iter             = 0;
184237ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1843a8054027SBarry Smith   snes->lagpreconditioner    = 1;
184437ec4e1aSPeter Brune   snes->pre_iter             = 0;
184537ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1846639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1847c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18489e5d0892SLisandro Dalcin   snes->data                 = NULL;
18494dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1850186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18516f24a144SLois Curfman McInnes   snes->nwork                = 0;
18529e5d0892SLisandro Dalcin   snes->work                 = NULL;
185358c9b817SLisandro Dalcin   snes->nvwork               = 0;
18549e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1855758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1856758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18570298fd71SBarry Smith   snes->conv_hist            = NULL;
18580298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1859758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1860971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1861e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1862184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1863efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1864b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1865c40d0f55SPeter Brune 
1866d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1867d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1868d8f46077SPeter Brune   snes->mf_version  = 1;
1869d8f46077SPeter Brune 
18703d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18713d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18723d4c4710SBarry Smith 
1873349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
187476bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1875349187a7SBarry Smith 
18764fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18774fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
18784fc747eaSLawrence Mitchell 
18799b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18804dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1881f5af7f23SKarl Rupp 
18829b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
18839b94acceSBarry Smith   kctx->version     = 2;
18840f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
18859b94acceSBarry Smith                              this was too large for some test cases */
188675567043SBarry Smith   kctx->rtol_last   = 0.0;
18870f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
18889b94acceSBarry Smith   kctx->gamma       = 1.0;
18890f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
189071f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
18910f0abf79SStefano Zampini   kctx->threshold   = 0.1;
189275567043SBarry Smith   kctx->lresid_last = 0.0;
189375567043SBarry Smith   kctx->norm_last   = 0.0;
18949b94acceSBarry Smith 
18950f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
18960f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
18970f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
18980f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
18990f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19000f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19010f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19020f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19030f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19040f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19050f0abf79SStefano Zampini 
19069b94acceSBarry Smith   *outsnes = snes;
19073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19089b94acceSBarry Smith }
19099b94acceSBarry Smith 
19109b94acceSBarry Smith /*@C
19119b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1912f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19139b94acceSBarry Smith   equations.
19149b94acceSBarry Smith 
1915c3339decSBarry Smith   Logically Collective
1916fee21e36SBarry Smith 
1917c7afd0dbSLois Curfman McInnes   Input Parameters:
1918f6dfbefdSBarry Smith + snes - the `SNES` context
1919dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19208434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1921c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1922dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19239b94acceSBarry Smith 
192436851e7fSLois Curfman McInnes   Level: beginner
192536851e7fSLois Curfman McInnes 
19268434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19279b94acceSBarry Smith @*/
19288434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1929d71ae5a4SJacob Faibussowitsch {
19306cab3a1bSJed Brown   DM dm;
19316cab3a1bSJed Brown 
19323a40ed3dSBarry Smith   PetscFunctionBegin;
19330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1934d2a683ecSLisandro Dalcin   if (r) {
1935d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1936d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19379566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19389566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
193985385478SLisandro Dalcin     snes->vec_func = r;
1940d2a683ecSLisandro Dalcin   }
19419566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19429566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
194348a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19459b94acceSBarry Smith }
19469b94acceSBarry Smith 
1947e4ed7901SPeter Brune /*@C
19480b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1949e4ed7901SPeter Brune 
1950c3339decSBarry Smith   Logically Collective
1951e4ed7901SPeter Brune 
1952e4ed7901SPeter Brune   Input Parameters:
1953f6dfbefdSBarry Smith + snes - the `SNES` context
1954e4ed7901SPeter Brune - f    - vector to store function value
1955e4ed7901SPeter Brune 
1956dc4c0fb0SBarry Smith   Level: developer
1957dc4c0fb0SBarry Smith 
1958e4ed7901SPeter Brune   Notes:
1959e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1960e4ed7901SPeter Brune 
1961f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1962e4ed7901SPeter Brune 
19631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1964e4ed7901SPeter Brune @*/
1965d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1966d71ae5a4SJacob Faibussowitsch {
1967e4ed7901SPeter Brune   Vec vec_func;
1968e4ed7901SPeter Brune 
1969e4ed7901SPeter Brune   PetscFunctionBegin;
1970e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1971e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1972e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1973efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1974902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19753ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1976902f982fSPeter Brune   }
19779566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19789566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1979f5af7f23SKarl Rupp 
1980217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1982e4ed7901SPeter Brune }
1983e4ed7901SPeter Brune 
1984534ebe21SPeter Brune /*@
1985f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1986f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1987534ebe21SPeter Brune 
1988c3339decSBarry Smith   Logically Collective
1989534ebe21SPeter Brune 
1990534ebe21SPeter Brune   Input Parameters:
1991f6dfbefdSBarry Smith + snes         - the `SNES` context
1992365a6726SPeter Brune - normschedule - the frequency of norm computation
1993534ebe21SPeter Brune 
1994517f1916SMatthew G. Knepley   Options Database Key:
199567b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1996517f1916SMatthew G. Knepley 
1997dc4c0fb0SBarry Smith   Level: advanced
1998dc4c0fb0SBarry Smith 
1999534ebe21SPeter Brune   Notes:
2000f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2001534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2002534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2003f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2004534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2005534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2006534ebe21SPeter Brune   their solution.
2007534ebe21SPeter Brune 
2008e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2009534ebe21SPeter Brune @*/
2010d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2011d71ae5a4SJacob Faibussowitsch {
2012534ebe21SPeter Brune   PetscFunctionBegin;
2013534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2014365a6726SPeter Brune   snes->normschedule = normschedule;
20153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2016534ebe21SPeter Brune }
2017534ebe21SPeter Brune 
2018534ebe21SPeter Brune /*@
2019f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2020f6dfbefdSBarry Smith   of the `SNES` method.
2021534ebe21SPeter Brune 
2022c3339decSBarry Smith   Logically Collective
2023534ebe21SPeter Brune 
2024534ebe21SPeter Brune   Input Parameters:
2025f6dfbefdSBarry Smith + snes         - the `SNES` context
2026365a6726SPeter Brune - normschedule - the type of the norm used
2027534ebe21SPeter Brune 
2028534ebe21SPeter Brune   Level: advanced
2029534ebe21SPeter Brune 
20301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2031534ebe21SPeter Brune @*/
2032d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2033d71ae5a4SJacob Faibussowitsch {
2034534ebe21SPeter Brune   PetscFunctionBegin;
2035534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2036365a6726SPeter Brune   *normschedule = snes->normschedule;
20373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2038534ebe21SPeter Brune }
2039534ebe21SPeter Brune 
2040c5ce4427SMatthew G. Knepley /*@
2041c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2042c5ce4427SMatthew G. Knepley 
2043c3339decSBarry Smith   Logically Collective
2044c5ce4427SMatthew G. Knepley 
2045c5ce4427SMatthew G. Knepley   Input Parameters:
2046f6dfbefdSBarry Smith + snes - the `SNES` context
2047f6dfbefdSBarry Smith - norm - the value of the norm
2048c5ce4427SMatthew G. Knepley 
2049c5ce4427SMatthew G. Knepley   Level: developer
2050c5ce4427SMatthew G. Knepley 
20511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2052c5ce4427SMatthew G. Knepley @*/
2053d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2054d71ae5a4SJacob Faibussowitsch {
2055c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2056c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2057c5ce4427SMatthew G. Knepley   snes->norm = norm;
20583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2059c5ce4427SMatthew G. Knepley }
2060c5ce4427SMatthew G. Knepley 
2061c5ce4427SMatthew G. Knepley /*@
2062c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2063c5ce4427SMatthew G. Knepley 
2064c5ce4427SMatthew G. Knepley   Not Collective
2065c5ce4427SMatthew G. Knepley 
2066c5ce4427SMatthew G. Knepley   Input Parameter:
2067f6dfbefdSBarry Smith . snes - the `SNES` context
2068c5ce4427SMatthew G. Knepley 
2069c5ce4427SMatthew G. Knepley   Output Parameter:
2070c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2071c5ce4427SMatthew G. Knepley 
2072c5ce4427SMatthew G. Knepley   Level: developer
2073c5ce4427SMatthew G. Knepley 
20741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2075c5ce4427SMatthew G. Knepley @*/
2076d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2077d71ae5a4SJacob Faibussowitsch {
2078c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2079c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20804f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2081c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2083c5ce4427SMatthew G. Knepley }
2084c5ce4427SMatthew G. Knepley 
2085c1e67a49SFande Kong /*@
2086f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2087c1e67a49SFande Kong 
2088c1e67a49SFande Kong   Not Collective
2089c1e67a49SFande Kong 
2090c1e67a49SFande Kong   Input Parameter:
2091f6dfbefdSBarry Smith . snes - the `SNES` context
2092c1e67a49SFande Kong 
2093c1e67a49SFande Kong   Output Parameter:
2094c1e67a49SFande Kong . ynorm - the last computed update norm
2095c1e67a49SFande Kong 
2096c1e67a49SFande Kong   Level: developer
2097c1e67a49SFande Kong 
2098f6dfbefdSBarry Smith   Note:
2099f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2100f6dfbefdSBarry Smith 
21011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2102c1e67a49SFande Kong @*/
2103d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2104d71ae5a4SJacob Faibussowitsch {
2105c1e67a49SFande Kong   PetscFunctionBegin;
2106c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21074f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2108c1e67a49SFande Kong   *ynorm = snes->ynorm;
21093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2110c1e67a49SFande Kong }
2111c1e67a49SFande Kong 
2112c1e67a49SFande Kong /*@
21134591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2114c1e67a49SFande Kong 
2115c1e67a49SFande Kong   Not Collective
2116c1e67a49SFande Kong 
2117c1e67a49SFande Kong   Input Parameter:
2118f6dfbefdSBarry Smith . snes - the `SNES` context
2119c1e67a49SFande Kong 
2120c1e67a49SFande Kong   Output Parameter:
2121c1e67a49SFande Kong . xnorm - the last computed solution norm
2122c1e67a49SFande Kong 
2123c1e67a49SFande Kong   Level: developer
2124c1e67a49SFande Kong 
21251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2126c1e67a49SFande Kong @*/
2127d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2128d71ae5a4SJacob Faibussowitsch {
2129c1e67a49SFande Kong   PetscFunctionBegin;
2130c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21314f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2132c1e67a49SFande Kong   *xnorm = snes->xnorm;
21333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2134c1e67a49SFande Kong }
2135c1e67a49SFande Kong 
2136cc4c1da9SBarry Smith /*@
2137f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2138f6dfbefdSBarry Smith   of the `SNES` method.
213947073ea2SPeter Brune 
2140c3339decSBarry Smith   Logically Collective
214147073ea2SPeter Brune 
214247073ea2SPeter Brune   Input Parameters:
2143f6dfbefdSBarry Smith + snes - the `SNES` context
2144f6dfbefdSBarry Smith - type - the function type
214547073ea2SPeter Brune 
214647073ea2SPeter Brune   Level: developer
214747073ea2SPeter Brune 
2148420bcc1bSBarry Smith   Values of the function type\:
2149f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2150f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2151f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2152f6dfbefdSBarry Smith 
2153420bcc1bSBarry Smith   Note:
2154f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2155f6dfbefdSBarry Smith 
21561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
215747073ea2SPeter Brune @*/
2158d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2159d71ae5a4SJacob Faibussowitsch {
216047073ea2SPeter Brune   PetscFunctionBegin;
216147073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
216247073ea2SPeter Brune   snes->functype = type;
21633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216447073ea2SPeter Brune }
216547073ea2SPeter Brune 
2166cc4c1da9SBarry Smith /*@
2167f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
216847073ea2SPeter Brune   of the SNES method.
216947073ea2SPeter Brune 
2170c3339decSBarry Smith   Logically Collective
217147073ea2SPeter Brune 
217247073ea2SPeter Brune   Input Parameters:
2173f6dfbefdSBarry Smith + snes - the `SNES` context
2174f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
217547073ea2SPeter Brune 
217647073ea2SPeter Brune   Level: advanced
217747073ea2SPeter Brune 
21781cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
217947073ea2SPeter Brune @*/
2180d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2181d71ae5a4SJacob Faibussowitsch {
218247073ea2SPeter Brune   PetscFunctionBegin;
218347073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
218447073ea2SPeter Brune   *type = snes->functype;
21853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2186534ebe21SPeter Brune }
2187534ebe21SPeter Brune 
2188c79ef259SPeter Brune /*@C
2189be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2190c79ef259SPeter Brune   use with composed nonlinear solvers.
2191c79ef259SPeter Brune 
2192c79ef259SPeter Brune   Input Parameters:
21939bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
21948434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
2195*77e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2196c79ef259SPeter Brune 
2197dc4c0fb0SBarry Smith   Level: intermediate
2198dc4c0fb0SBarry Smith 
2199f6dfbefdSBarry Smith   Note:
2200f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2201f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2202c79ef259SPeter Brune 
22038434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2204c79ef259SPeter Brune @*/
22058434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2206d71ae5a4SJacob Faibussowitsch {
22076cab3a1bSJed Brown   DM dm;
22086cab3a1bSJed Brown 
2209646217ecSPeter Brune   PetscFunctionBegin;
22106cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22119566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22129566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2214646217ecSPeter Brune }
2215646217ecSPeter Brune 
2216bbc1464cSBarry Smith /*
2217bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2218bbc1464cSBarry Smith    changed during the KSPSolve()
2219bbc1464cSBarry Smith */
2220d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2221d71ae5a4SJacob Faibussowitsch {
2222bbc1464cSBarry Smith   DM     dm;
2223bbc1464cSBarry Smith   DMSNES sdm;
2224bbc1464cSBarry Smith 
2225bbc1464cSBarry Smith   PetscFunctionBegin;
22269566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22279566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2228bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2229bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2230792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22319566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22320df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2233ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2234792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22359566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2236bbc1464cSBarry Smith   } else {
2237792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22389566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2239bbc1464cSBarry Smith   }
22403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2241bbc1464cSBarry Smith }
2242bbc1464cSBarry Smith 
2243d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2244d71ae5a4SJacob Faibussowitsch {
2245e03ab78fSPeter Brune   DM     dm;
2246942e3340SBarry Smith   DMSNES sdm;
22476cab3a1bSJed Brown 
22488b0a5094SBarry Smith   PetscFunctionBegin;
22499566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22509566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22518b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2252bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2253792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22549566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2255792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22569566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2257bbc1464cSBarry Smith   } else {
2258792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22599566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2260bbc1464cSBarry Smith   }
22613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22628b0a5094SBarry Smith }
22638b0a5094SBarry Smith 
2264d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2265d71ae5a4SJacob Faibussowitsch {
22668b0a5094SBarry Smith   PetscFunctionBegin;
2267e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2268bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22699566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22709566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22728b0a5094SBarry Smith }
22738b0a5094SBarry Smith 
22748b0a5094SBarry Smith /*@C
22751d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22768b0a5094SBarry Smith 
2277c3339decSBarry Smith   Logically Collective
22788b0a5094SBarry Smith 
22798b0a5094SBarry Smith   Input Parameters:
2280f6dfbefdSBarry Smith + snes - the `SNES` context
2281dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
22828434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
22836b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2284dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
22858434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2286dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2287dc4c0fb0SBarry Smith 
2288dc4c0fb0SBarry Smith   Level: intermediate
22898b0a5094SBarry Smith 
22908b0a5094SBarry Smith   Notes:
22916b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2292f450aa47SBarry 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.
2293f450aa47SBarry Smith 
2294f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22958b0a5094SBarry Smith 
22961d27aa22SBarry 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}$.
22971d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
22988b0a5094SBarry Smith 
2299dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
23008b0a5094SBarry Smith 
23010d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23021d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23038b0a5094SBarry Smith 
23048b0a5094SBarry 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
23051d27aa22SBarry 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
23061d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23078b0a5094SBarry Smith 
23081d27aa22SBarry 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
2309f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
23106b7fb656SBarry Smith 
231115229ffcSPierre 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.
23126b7fb656SBarry Smith 
2313dc4c0fb0SBarry 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
23146b7fb656SBarry 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
2315f6dfbefdSBarry 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`.
2316aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2317bbc1464cSBarry Smith 
23189bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23198434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23208b0a5094SBarry Smith @*/
23218434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2322d71ae5a4SJacob Faibussowitsch {
2323e03ab78fSPeter Brune   DM dm;
2324e03ab78fSPeter Brune 
23258b0a5094SBarry Smith   PetscFunctionBegin;
23268b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23279566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23289566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23299566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23309566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23319566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23338b0a5094SBarry Smith }
23348b0a5094SBarry Smith 
23357971a8bfSPeter Brune /*@C
23367971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23377971a8bfSPeter Brune 
2338f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23397971a8bfSPeter Brune 
23407971a8bfSPeter Brune   Input Parameter:
2341f6dfbefdSBarry Smith . snes - the `SNES` context
23427971a8bfSPeter Brune 
2343d8d19677SJose E. Roman   Output Parameters:
2344dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23458434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2346dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2347dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23488434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2349dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23507971a8bfSPeter Brune 
23517971a8bfSPeter Brune   Level: advanced
23527971a8bfSPeter Brune 
23538434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23547971a8bfSPeter Brune @*/
23558434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2356d71ae5a4SJacob Faibussowitsch {
23577971a8bfSPeter Brune   DM dm;
23587971a8bfSPeter Brune 
23597971a8bfSPeter Brune   PetscFunctionBegin;
23607971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23619566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23629566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23639566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23649566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23667971a8bfSPeter Brune }
23677971a8bfSPeter Brune 
2368d25893d9SBarry Smith /*@C
2369dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2370d25893d9SBarry Smith 
2371c3339decSBarry Smith   Logically Collective
2372d25893d9SBarry Smith 
2373d25893d9SBarry Smith   Input Parameters:
2374f6dfbefdSBarry Smith + snes - the `SNES` context
23758434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2376d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2377dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2378d25893d9SBarry Smith 
2379d25893d9SBarry Smith   Level: intermediate
2380d25893d9SBarry Smith 
23818434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2382d25893d9SBarry Smith @*/
23838434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2384d71ae5a4SJacob Faibussowitsch {
2385d25893d9SBarry Smith   PetscFunctionBegin;
2386d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2387d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2388d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2390d25893d9SBarry Smith }
2391d25893d9SBarry Smith 
23921096aae1SMatthew Knepley /*@C
2393dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2394dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
23951096aae1SMatthew Knepley 
2396c3339decSBarry Smith   Logically Collective
23971096aae1SMatthew Knepley 
23981096aae1SMatthew Knepley   Input Parameter:
2399f6dfbefdSBarry Smith . snes - the `SNES` context
24001096aae1SMatthew Knepley 
24011096aae1SMatthew Knepley   Output Parameter:
2402dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24031096aae1SMatthew Knepley 
24041096aae1SMatthew Knepley   Level: intermediate
24051096aae1SMatthew Knepley 
24061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24071096aae1SMatthew Knepley @*/
2408d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2409d71ae5a4SJacob Faibussowitsch {
24101096aae1SMatthew Knepley   PetscFunctionBegin;
24110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24124f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
241385385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24151096aae1SMatthew Knepley }
24161096aae1SMatthew Knepley 
24179b94acceSBarry Smith /*@
2418f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24199b94acceSBarry Smith 
2420c3339decSBarry Smith   Collective
2421c7afd0dbSLois Curfman McInnes 
24229b94acceSBarry Smith   Input Parameters:
2423f6dfbefdSBarry Smith + snes - the `SNES` context
2424c7afd0dbSLois Curfman McInnes - x    - input vector
24259b94acceSBarry Smith 
24269b94acceSBarry Smith   Output Parameter:
2427f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24289b94acceSBarry Smith 
2429dc4c0fb0SBarry Smith   Level: developer
2430dc4c0fb0SBarry Smith 
243100677de2SStefano Zampini   Notes:
2432f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2433bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
243436851e7fSLois Curfman McInnes 
243500677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
243600677de2SStefano Zampini 
24371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24389b94acceSBarry Smith @*/
2439d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2440d71ae5a4SJacob Faibussowitsch {
24416cab3a1bSJed Brown   DM     dm;
2442942e3340SBarry Smith   DMSNES sdm;
24439b94acceSBarry Smith 
24443a40ed3dSBarry Smith   PetscFunctionBegin;
24450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24460700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24470700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2448c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2449c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2450e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2451184914b5SBarry Smith 
24529566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24539566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24540fdf79fbSJacob 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().");
245532f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
245648a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24579566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24588ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24598ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2460800f99ffSJeremy L Thompson     {
2461800f99ffSJeremy L Thompson       void           *ctx;
24628434afd1SBarry Smith       SNESFunctionFn *computefunction;
2463800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2464800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2465800f99ffSJeremy L Thompson     }
24669566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
246748a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24680fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24699566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24700fdf79fbSJacob Faibussowitsch   }
24711baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2472ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2473422a814eSBarry Smith   /*
2474422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2475422a814eSBarry Smith      propagate the value to all processes
2476422a814eSBarry Smith   */
2477f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
24783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24799b94acceSBarry Smith }
24809b94acceSBarry Smith 
2481c79ef259SPeter Brune /*@
2482f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2483bbc1464cSBarry Smith 
2484c3339decSBarry Smith   Collective
2485bbc1464cSBarry Smith 
2486bbc1464cSBarry Smith   Input Parameters:
2487f6dfbefdSBarry Smith + snes - the `SNES` context
2488bbc1464cSBarry Smith - x    - input vector
2489bbc1464cSBarry Smith 
2490bbc1464cSBarry Smith   Output Parameter:
2491f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2492bbc1464cSBarry Smith 
2493dc4c0fb0SBarry Smith   Level: developer
2494dc4c0fb0SBarry Smith 
2495bbc1464cSBarry Smith   Notes:
2496420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2497bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2498bbc1464cSBarry Smith 
2499dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2500f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2501dd8e379bSPierre 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.
2502bbc1464cSBarry Smith 
25031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2504bbc1464cSBarry Smith @*/
2505d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2506d71ae5a4SJacob Faibussowitsch {
2507bbc1464cSBarry Smith   DM     dm;
2508bbc1464cSBarry Smith   DMSNES sdm;
2509bbc1464cSBarry Smith 
2510bbc1464cSBarry Smith   PetscFunctionBegin;
2511bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2512bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2513bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2514bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2515bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2516e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2517bbc1464cSBarry Smith 
25189566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25199566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25219566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2522bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2523bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2524792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25259566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2527bbc1464cSBarry Smith   snes->nfuncs++;
2528bbc1464cSBarry Smith   /*
2529bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2530bbc1464cSBarry Smith      propagate the value to all processes
2531bbc1464cSBarry Smith   */
2532f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2534bbc1464cSBarry Smith }
2535bbc1464cSBarry Smith 
2536bbc1464cSBarry Smith /*@
2537f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2538c79ef259SPeter Brune 
2539c3339decSBarry Smith   Collective
2540c79ef259SPeter Brune 
2541c79ef259SPeter Brune   Input Parameters:
2542f6dfbefdSBarry Smith + snes - the `SNES` context
2543c79ef259SPeter Brune . x    - input vector
2544c79ef259SPeter Brune - b    - rhs vector
2545c79ef259SPeter Brune 
2546c79ef259SPeter Brune   Output Parameter:
2547c79ef259SPeter Brune . x - new solution vector
2548c79ef259SPeter Brune 
2549dc4c0fb0SBarry Smith   Level: developer
2550dc4c0fb0SBarry Smith 
2551f6dfbefdSBarry Smith   Note:
2552f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2553c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2554c79ef259SPeter Brune   themselves.
2555c79ef259SPeter Brune 
25568434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2557c79ef259SPeter Brune @*/
2558d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2559d71ae5a4SJacob Faibussowitsch {
25606cab3a1bSJed Brown   DM     dm;
2561942e3340SBarry Smith   DMSNES sdm;
2562646217ecSPeter Brune 
2563646217ecSPeter Brune   PetscFunctionBegin;
2564646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2565064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2566064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2567064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2568064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2569e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25709566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25719566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25729566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25730fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25749566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2575792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25769566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2579646217ecSPeter Brune }
2580646217ecSPeter Brune 
2581494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2582494a190aSStefano Zampini {
2583494a190aSStefano Zampini   Vec          X;
2584494a190aSStefano Zampini   PetscScalar *g;
2585494a190aSStefano Zampini   PetscReal    f, f2;
2586494a190aSStefano Zampini   PetscInt     low, high, N, i;
2587494a190aSStefano Zampini   PetscBool    flg;
2588494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2589494a190aSStefano Zampini 
2590494a190aSStefano Zampini   PetscFunctionBegin;
2591494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2592494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2593494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2594494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2595494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2596494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2597494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2598494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2599494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2600494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2601494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2602494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2603494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2604494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2605494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2606494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2607494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2608494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2609494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2610494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2611494a190aSStefano Zampini   }
2612494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2613494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2614494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2615494a190aSStefano Zampini }
2616494a190aSStefano Zampini 
2617494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2618494a190aSStefano Zampini {
2619494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2620494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2621494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2622494a190aSStefano Zampini   PetscScalar       dot;
2623494a190aSStefano Zampini   MPI_Comm          comm;
2624494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2625494a190aSStefano Zampini   PetscViewerFormat format;
2626494a190aSStefano Zampini   PetscInt          tabs;
2627494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26288434afd1SBarry Smith   SNESObjectiveFn  *objective;
2629494a190aSStefano Zampini 
2630494a190aSStefano Zampini   PetscFunctionBegin;
2631494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2632494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2633494a190aSStefano Zampini 
2634494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2635494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2636494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2637494a190aSStefano Zampini   PetscOptionsEnd();
2638494a190aSStefano Zampini   if (!test) {
2639494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2640494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2641494a190aSStefano Zampini   }
2642494a190aSStefano Zampini 
2643494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2644494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2645494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2646494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2647494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2648494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2649494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2650494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2651494a190aSStefano Zampini   }
2652494a190aSStefano Zampini   if (!directionsprinted) {
2653494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2654494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2655494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2656494a190aSStefano Zampini   }
2657494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2658494a190aSStefano Zampini 
2659494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2660494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2661494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2662494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2663494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2664494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2665494a190aSStefano Zampini 
2666494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2667494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2668494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2669494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2670494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2671494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2672494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2673494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2674494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2675494a190aSStefano 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))));
2676494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2677494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2678494a190aSStefano Zampini 
2679494a190aSStefano Zampini   if (complete_print) {
2680494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2681494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2682494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2683494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2684494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2685494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2686494a190aSStefano Zampini   }
2687494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2688494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2689494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2690494a190aSStefano Zampini 
2691494a190aSStefano Zampini   if (complete_print) {
2692494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2693494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2694494a190aSStefano Zampini   }
2695494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2696494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2697494a190aSStefano Zampini }
2698494a190aSStefano Zampini 
2699d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2700d71ae5a4SJacob Faibussowitsch {
270112837594SBarry Smith   Mat               A, B, C, D, jacobian;
27024df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2703e885f1abSBarry Smith   PetscReal         nrm, gnorm;
270481e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27050e276705SLisandro Dalcin   MatType           mattype;
2706e885f1abSBarry Smith   PetscInt          m, n, M, N;
2707e885f1abSBarry Smith   void             *functx;
27082cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
27093325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2710e885f1abSBarry Smith   MPI_Comm          comm;
2711e885f1abSBarry Smith   PetscInt          tabs;
271212837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27133325ff46SBarry Smith   PetscViewerFormat format;
2714e885f1abSBarry Smith 
2715e885f1abSBarry Smith   PetscFunctionBegin;
2716d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
27189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27204ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27229566063dSJacob 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));
2723d0609cedSBarry Smith   PetscOptionsEnd();
27243ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2725e885f1abSBarry Smith 
27269566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27279566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27289566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27299566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27309566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
273112837594SBarry Smith   if (!complete_print && !directionsprinted) {
27329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
273412837594SBarry Smith   }
273512837594SBarry Smith   if (!directionsprinted) {
27369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
27379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
273812837594SBarry Smith     directionsprinted = PETSC_TRUE;
2739e885f1abSBarry Smith   }
27401baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2741e885f1abSBarry Smith 
27429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
274312837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
274412837594SBarry Smith   else jacobian = snes->jacobian_pre;
274512837594SBarry Smith 
27464df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
27474df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
27489566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
27494df93895SStefano Zampini 
2750a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
27519566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
27529566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
27539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
275412837594SBarry Smith   while (jacobian) {
27552cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
27562cd624f9SStefano Zampini 
27572cd624f9SStefano Zampini     if (istranspose) {
27589566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
27592cd624f9SStefano Zampini       Jsave    = jacobian;
27602cd624f9SStefano Zampini       jacobian = JT;
27612cd624f9SStefano Zampini     }
27629566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
276312837594SBarry Smith     if (flg) {
276412837594SBarry Smith       A = jacobian;
27659566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
276612837594SBarry Smith     } else {
27679566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
276812837594SBarry Smith     }
2769e885f1abSBarry Smith 
27709566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
27719566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
27729566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
27739566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
27749566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
27759566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
27769566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
27779566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
27789566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2779e885f1abSBarry Smith 
27809566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
27819566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
278212837594SBarry Smith 
27839566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
27849566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
27859566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
27869566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
27879566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
278812837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
27899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
279012837594SBarry Smith 
2791e885f1abSBarry Smith     if (complete_print) {
27929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
27939566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
27949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
27959566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2796e885f1abSBarry Smith     }
2797e885f1abSBarry Smith 
2798df10fb39SFande Kong     if (threshold_print || complete_print) {
2799e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2800e885f1abSBarry Smith       PetscScalar       *cvals;
2801e885f1abSBarry Smith       const PetscInt    *bcols;
2802e885f1abSBarry Smith       const PetscScalar *bvals;
2803e885f1abSBarry Smith 
28049566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28059566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28069566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28079566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28089566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28099566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28100e276705SLisandro Dalcin 
28119566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28129566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2813e885f1abSBarry Smith 
2814e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28159566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28169566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2817e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
281823a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2819e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2820e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2821e885f1abSBarry Smith             cncols += 1;
2822e885f1abSBarry Smith           }
2823e885f1abSBarry Smith         }
282448a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28259566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28269566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2827e885f1abSBarry Smith       }
28289566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28299566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28319566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28329566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2833e885f1abSBarry Smith     }
28349566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
28359566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
28369566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
28372cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
283812837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
283912837594SBarry Smith       jacobian = snes->jacobian_pre;
28409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
28419371c9d4SSatish Balay     } else jacobian = NULL;
284212837594SBarry Smith   }
28439566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
28441baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2845648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
28469566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
28473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2848e885f1abSBarry Smith }
2849e885f1abSBarry Smith 
285062fef451SLois Curfman McInnes /*@
2851f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
285262fef451SLois Curfman McInnes 
2853c3339decSBarry Smith   Collective
2854c7afd0dbSLois Curfman McInnes 
285562fef451SLois Curfman McInnes   Input Parameters:
2856f6dfbefdSBarry Smith + snes - the `SNES` context
2857e4094ef1SJacob Faibussowitsch - X    - input vector
285862fef451SLois Curfman McInnes 
285962fef451SLois Curfman McInnes   Output Parameters:
2860c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2861420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2862fee21e36SBarry Smith 
2863e35cf81dSBarry Smith   Options Database Keys:
286467b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
286567b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2866455a5933SJed 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.
2867455a5933SJed 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
2868693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2869693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2870693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
28714c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
287294d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2873a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2874c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2875dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2876dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2877a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2878a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2879c01495d3SJed Brown 
2880dc4c0fb0SBarry Smith   Level: developer
2881dc4c0fb0SBarry Smith 
2882f6dfbefdSBarry Smith   Note:
288362fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
288462fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
288562fef451SLois Curfman McInnes 
2886420bcc1bSBarry Smith   Developer Note:
2887dc4c0fb0SBarry 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
2888420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2889e885f1abSBarry Smith 
28901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
289162fef451SLois Curfman McInnes @*/
2892d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2893d71ae5a4SJacob Faibussowitsch {
2894ace3abfcSBarry Smith   PetscBool flag;
28956cab3a1bSJed Brown   DM        dm;
2896942e3340SBarry Smith   DMSNES    sdm;
2897e0e3a89bSBarry Smith   KSP       ksp;
28983a40ed3dSBarry Smith 
28993a40ed3dSBarry Smith   PetscFunctionBegin;
29000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29010700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2902c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2903e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29049566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29059566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29063232da50SPeter Brune 
290701c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2908fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2909fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2910f5af7f23SKarl Rupp 
29119566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2912fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29139566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29149566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2915ebd3b9afSBarry Smith     if (flag) {
29169566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29179566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2918ebd3b9afSBarry Smith     }
29193ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
292037ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
292163a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29229566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2923ebd3b9afSBarry Smith     if (flag) {
29249566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29259566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2926ebd3b9afSBarry Smith     }
29273ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2928e35cf81dSBarry Smith   }
2929efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29309566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29319566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29323ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2933d728fb7dSPeter Brune   }
2934e35cf81dSBarry Smith 
29359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
29369566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2937800f99ffSJeremy L Thompson   {
2938800f99ffSJeremy L Thompson     void           *ctx;
29398434afd1SBarry Smith     SNESJacobianFn *J;
2940800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2941800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2942800f99ffSJeremy L Thompson   }
29439566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
29449566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
294528d58a37SPierre Jolivet 
294628d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
29479566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2948a8054027SBarry Smith 
2949e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
29509566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
29513b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
29529566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
29539566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
29543b4f5425SBarry Smith     snes->lagpreconditioner = -1;
29553b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
29569566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
29579566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
295837ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
295963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
29609566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2961d1e9a80fSBarry Smith   } else {
29629566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
29639566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2964a8054027SBarry Smith   }
2965a8054027SBarry Smith 
29664df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
29674df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
29684df93895SStefano Zampini   {
29694df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
29704df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
29714df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
29724df93895SStefano Zampini 
29734df93895SStefano Zampini     snes->vec_sol      = X;
29744df93895SStefano Zampini     snes->jacobian     = A;
29754df93895SStefano Zampini     snes->jacobian_pre = B;
2976494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
29779566063dSJacob Faibussowitsch     PetscCall(SNESTestJacobian(snes));
2978494a190aSStefano Zampini 
29794df93895SStefano Zampini     snes->vec_sol      = xsave;
29804df93895SStefano Zampini     snes->jacobian     = jacobiansave;
29814df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
29824df93895SStefano Zampini   }
29834df93895SStefano Zampini 
2984693365a8SJed Brown   {
2985693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
2986648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
2987648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
2988648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
2989648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2990693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
29910298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2992693365a8SJed Brown       PetscViewer vdraw, vstdout;
29936b3a5b13SJed Brown       PetscBool   flg;
2994693365a8SJed Brown       if (flag_operator) {
29959566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2996693365a8SJed Brown         Bexp = Bexp_mine;
2997693365a8SJed Brown       } else {
2998693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
29999566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
300094ab13aaSBarry Smith         if (flg) Bexp = B;
3001693365a8SJed Brown         else {
3002693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30039566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3004693365a8SJed Brown           Bexp = Bexp_mine;
3005693365a8SJed Brown         }
3006693365a8SJed Brown       }
30079566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30089566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3010693365a8SJed Brown       if (flag_draw || flag_contour) {
30119566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30129566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30130298fd71SBarry Smith       } else vdraw = NULL;
30149566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30159566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30169566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30189566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30199566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30209566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30229566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3023693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30249566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30259566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30269566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3027693365a8SJed Brown       }
30289566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30299566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30309566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30319566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3032693365a8SJed Brown     }
3033693365a8SJed Brown   }
30344c30e9fbSJed Brown   {
30356719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
30366719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3037648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3038648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3039648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3040648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3041648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
304227b0f280SBarry Smith     if (flag_threshold) {
30439566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
30449566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
304527b0f280SBarry Smith     }
30466719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
30474c30e9fbSJed Brown       Mat             Bfd;
30484c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3049335efc43SPeter Brune       MatColoring     coloring;
30504c30e9fbSJed Brown       ISColoring      iscoloring;
30514c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
30528434afd1SBarry Smith       SNESFunctionFn *func;
30534c30e9fbSJed Brown       void           *funcctx;
30546719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
30554c30e9fbSJed Brown 
30569566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
30579566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
30589566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
30599566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
30609566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
30619566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
30629566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
30639566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30649566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
30659566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
30664c30e9fbSJed Brown 
30674c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
30689566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
30699566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
30709566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
30719566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
30729566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30739566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
30749566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
30754c30e9fbSJed Brown 
30769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
30774c30e9fbSJed Brown       if (flag_draw || flag_contour) {
30789566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30799566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30800298fd71SBarry Smith       } else vdraw = NULL;
30819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
30829566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
30839566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
30849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
30859566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30869566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
30879566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
30889566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
30899566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
30909566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
30919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
30929566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30934c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
30949566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30959566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
30969566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
30974c30e9fbSJed Brown       }
30989566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30996719d8e4SJed Brown 
31006719d8e4SJed Brown       if (flag_threshold) {
31016719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31029566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31039566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31046719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31056719d8e4SJed Brown           const PetscScalar *ba, *ca;
31066719d8e4SJed Brown           const PetscInt    *bj, *cj;
31076719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31086719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31099566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31109566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31115f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31126719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31136719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31146719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31156719d8e4SJed Brown               maxentrycol = bj[j];
31166719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31176719d8e4SJed Brown             }
31186719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31196719d8e4SJed Brown               maxdiffcol = bj[j];
31206719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31216719d8e4SJed Brown             }
31226719d8e4SJed Brown             if (rdiff > maxrdiff) {
31236719d8e4SJed Brown               maxrdiffcol = bj[j];
31246719d8e4SJed Brown               maxrdiff    = rdiff;
31256719d8e4SJed Brown             }
31266719d8e4SJed Brown           }
31276719d8e4SJed Brown           if (maxrdiff > 1) {
312863a3b9bcSJacob 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));
31296719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31306719d8e4SJed Brown               PetscReal rdiff;
31316719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
313248a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
31336719d8e4SJed Brown             }
313463a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
31356719d8e4SJed Brown           }
31369566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
31379566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
31386719d8e4SJed Brown         }
31396719d8e4SJed Brown       }
31409566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
31419566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
31424c30e9fbSJed Brown     }
31434c30e9fbSJed Brown   }
31443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31459b94acceSBarry Smith }
31469b94acceSBarry Smith 
31479b94acceSBarry Smith /*@C
31489b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3149044dda88SLois Curfman McInnes   location to store the matrix.
31509b94acceSBarry Smith 
3151c3339decSBarry Smith   Logically Collective
3152c7afd0dbSLois Curfman McInnes 
31539b94acceSBarry Smith   Input Parameters:
3154f6dfbefdSBarry Smith + snes - the `SNES` context
3155e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3156dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
31578434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3158c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3159dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3160dc4c0fb0SBarry Smith 
3161dc4c0fb0SBarry Smith   Level: beginner
31629b94acceSBarry Smith 
31639b94acceSBarry Smith   Notes:
3164dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
316516913363SBarry Smith   each matrix.
316616913363SBarry Smith 
3167dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3168dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3169895c21f2SBarry Smith 
3170dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3171f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3172a8a26c1eSJed Brown 
3173c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3174f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3175c3cc8fd1SJed Brown 
31761cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
31778434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
31789b94acceSBarry Smith @*/
31798434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3180d71ae5a4SJacob Faibussowitsch {
31816cab3a1bSJed Brown   DM dm;
31823a7fca6bSBarry Smith 
31833a40ed3dSBarry Smith   PetscFunctionBegin;
31840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3185e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3186e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3187e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3188e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
31899566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31909566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3191e5d3d808SBarry Smith   if (Amat) {
31929566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
31939566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3194f5af7f23SKarl Rupp 
3195e5d3d808SBarry Smith     snes->jacobian = Amat;
31963a7fca6bSBarry Smith   }
3197e5d3d808SBarry Smith   if (Pmat) {
31989566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
31999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3200f5af7f23SKarl Rupp 
3201e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32023a7fca6bSBarry Smith   }
32033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32049b94acceSBarry Smith }
320562fef451SLois Curfman McInnes 
3206c2aafc4cSSatish Balay /*@C
3207b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3208b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3209b4fd4287SBarry Smith 
3210420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3211c7afd0dbSLois Curfman McInnes 
3212b4fd4287SBarry Smith   Input Parameter:
3213b4fd4287SBarry Smith . snes - the nonlinear solver context
3214b4fd4287SBarry Smith 
3215b4fd4287SBarry Smith   Output Parameters:
3216dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3217dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32188434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3219dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3220fee21e36SBarry Smith 
322136851e7fSLois Curfman McInnes   Level: advanced
322236851e7fSLois Curfman McInnes 
32238434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3224b4fd4287SBarry Smith @*/
32258434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3226d71ae5a4SJacob Faibussowitsch {
32276cab3a1bSJed Brown   DM dm;
32286cab3a1bSJed Brown 
32293a40ed3dSBarry Smith   PetscFunctionBegin;
32300700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3231e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3232e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
32339566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3234800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
32353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3236b4fd4287SBarry Smith }
3237b4fd4287SBarry Smith 
3238d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3239d71ae5a4SJacob Faibussowitsch {
324058b371f3SBarry Smith   DM     dm;
324158b371f3SBarry Smith   DMSNES sdm;
324258b371f3SBarry Smith 
324358b371f3SBarry Smith   PetscFunctionBegin;
32449566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32459566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
324658b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
324758b371f3SBarry Smith     DM        dm;
324858b371f3SBarry Smith     PetscBool isdense, ismf;
324958b371f3SBarry Smith 
32509566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32519566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
32529566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
325358b371f3SBarry Smith     if (isdense) {
32549566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
325558b371f3SBarry Smith     } else if (!ismf) {
32569566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
325758b371f3SBarry Smith     }
325858b371f3SBarry Smith   }
32593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
326058b371f3SBarry Smith }
326158b371f3SBarry Smith 
32629b94acceSBarry Smith /*@
32639b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3264272ac6f2SLois Curfman McInnes   of a nonlinear solver.
32659b94acceSBarry Smith 
3266c3339decSBarry Smith   Collective
3267fee21e36SBarry Smith 
32682fe279fdSBarry Smith   Input Parameter:
3269f6dfbefdSBarry Smith . snes - the `SNES` context
3270c7afd0dbSLois Curfman McInnes 
3271dc4c0fb0SBarry Smith   Level: advanced
3272dc4c0fb0SBarry Smith 
3273f6dfbefdSBarry Smith   Note:
3274f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3275f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3276f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3277f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3278f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3279272ac6f2SLois Curfman McInnes 
32801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
32819b94acceSBarry Smith @*/
3282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3283d71ae5a4SJacob Faibussowitsch {
32846cab3a1bSJed Brown   DM             dm;
3285942e3340SBarry Smith   DMSNES         sdm;
3286c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
32876e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
32889b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
32899b5c1c08SStefano Zampini   Vec            f, fpc;
32909b5c1c08SStefano Zampini   void          *funcctx;
32919b5c1c08SStefano Zampini   void          *jacctx, *appctx;
32929b5c1c08SStefano Zampini   Mat            j, jpre;
32936b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
32946b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
32958434afd1SBarry Smith   SNESFunctionFn *func;
32968434afd1SBarry Smith   SNESJacobianFn *jac;
32973a40ed3dSBarry Smith 
32983a40ed3dSBarry Smith   PetscFunctionBegin;
32990700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33003ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3301fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33029b94acceSBarry Smith 
330348a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
330485385478SLisandro Dalcin 
33059566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
330658c9b817SLisandro Dalcin 
33079566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33089566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33099566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
331058b371f3SBarry Smith 
331148a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3312efd51863SBarry Smith 
331348a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3314b710008aSBarry Smith 
3315d8d34be6SBarry Smith   if (snes->linesearch) {
33169566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33179566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3318d8d34be6SBarry Smith   }
33199e764e56SPeter Brune 
33209b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3321b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3322172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3323172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3324172a4300SPeter Brune   }
3325d8f46077SPeter Brune 
3326efd4aadfSBarry Smith   if (snes->npc) {
33276e2a1849SPeter Brune     /* copy the DM over */
33289566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33299566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33306e2a1849SPeter Brune 
33319566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33329566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
33339566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
33349566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
33359566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
33369566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
33379566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
33389b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
33399566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
33406e2a1849SPeter Brune 
33416e2a1849SPeter Brune     /* copy the function pointers over */
33429566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
33436e2a1849SPeter Brune 
33446e2a1849SPeter Brune     /* default to 1 iteration */
33459566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3346efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
33479566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3348a9936a0cSPeter Brune     } else {
33499566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3350a9936a0cSPeter Brune     }
33519566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
33526e2a1849SPeter Brune 
33536e2a1849SPeter Brune     /* copy the line search context over */
3354d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
33559566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
33569566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
33579566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
33589566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
33599566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
33609566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
33619566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
33626e2a1849SPeter Brune     }
3363d8d34be6SBarry Smith   }
33641baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
33659927e4dfSBarry Smith   if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user));
33666e2a1849SPeter Brune 
336737ec4e1aSPeter Brune   snes->jac_iter = 0;
336837ec4e1aSPeter Brune   snes->pre_iter = 0;
336937ec4e1aSPeter Brune 
3370dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
337158c9b817SLisandro Dalcin 
33729566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
337358b371f3SBarry Smith 
3374b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
33756c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3376d8d34be6SBarry Smith       if (snes->linesearch) {
33779566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
33789566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
33796c67d002SPeter Brune       }
33806c67d002SPeter Brune     }
3381d8d34be6SBarry Smith   }
3382fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
33837aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
33843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33859b94acceSBarry Smith }
33869b94acceSBarry Smith 
338737596af1SLisandro Dalcin /*@
3388f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
338937596af1SLisandro Dalcin 
3390c3339decSBarry Smith   Collective
339137596af1SLisandro Dalcin 
339237596af1SLisandro Dalcin   Input Parameter:
3393f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
339437596af1SLisandro Dalcin 
3395d25893d9SBarry Smith   Level: intermediate
3396d25893d9SBarry Smith 
339795452b02SPatrick Sanan   Notes:
3398f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
339937596af1SLisandro Dalcin 
3400f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3401f6dfbefdSBarry Smith 
34021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
340337596af1SLisandro Dalcin @*/
3404d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3405d71ae5a4SJacob Faibussowitsch {
340637596af1SLisandro Dalcin   PetscFunctionBegin;
340737596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3408d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
34099927e4dfSBarry Smith     PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user));
34100298fd71SBarry Smith     snes->user = NULL;
3411d25893d9SBarry Smith   }
34121baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34138a23116dSBarry Smith 
3414dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34151baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34169e764e56SPeter Brune 
34171baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34189e764e56SPeter Brune 
34199566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34229566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34269566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34279566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3428f5af7f23SKarl Rupp 
342940fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
343040fdac6aSLawrence Mitchell 
343137596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
343237596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
34333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
343437596af1SLisandro Dalcin }
343537596af1SLisandro Dalcin 
343652baeb72SSatish Balay /*@
343736d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
343836d43d94SBarry Smith   removes the default viewer.
3439c4421ceaSFande Kong 
3440c3339decSBarry Smith   Collective
3441c4421ceaSFande Kong 
3442c4421ceaSFande Kong   Input Parameter:
3443f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3444c4421ceaSFande Kong 
3445c4421ceaSFande Kong   Level: intermediate
3446c4421ceaSFande Kong 
3447420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3448c4421ceaSFande Kong @*/
3449d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3450d71ae5a4SJacob Faibussowitsch {
3451c4421ceaSFande Kong   PetscInt i;
3452c4421ceaSFande Kong 
3453c4421ceaSFande Kong   PetscFunctionBegin;
3454c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3455c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
345648a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3457c4421ceaSFande Kong   }
3458c4421ceaSFande Kong   snes->numberreasonviews = 0;
3459648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
34603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3461c4421ceaSFande Kong }
3462c4421ceaSFande Kong 
34630764c050SBarry Smith /*@
34649b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3465f6dfbefdSBarry Smith   with `SNESCreate()`.
34669b94acceSBarry Smith 
3467c3339decSBarry Smith   Collective
3468c7afd0dbSLois Curfman McInnes 
34699b94acceSBarry Smith   Input Parameter:
3470f6dfbefdSBarry Smith . snes - the `SNES` context
34719b94acceSBarry Smith 
347236851e7fSLois Curfman McInnes   Level: beginner
347336851e7fSLois Curfman McInnes 
34741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
34759b94acceSBarry Smith @*/
3476d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3477d71ae5a4SJacob Faibussowitsch {
34783a40ed3dSBarry Smith   PetscFunctionBegin;
34793ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3480f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3481f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
34829371c9d4SSatish Balay     *snes = NULL;
34833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
34849371c9d4SSatish Balay   }
3485d4bb536fSBarry Smith 
3486f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
34879566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
34886b8b9a38SLisandro Dalcin 
3489e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
34909566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3491f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
34926d4c513bSLisandro Dalcin 
34939566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
34949566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
34959566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
34969566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
34976b8b9a38SLisandro Dalcin 
34989566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
349948a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
350048a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3501f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3502f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35039566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35059b94acceSBarry Smith }
35069b94acceSBarry Smith 
35079b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35089b94acceSBarry Smith 
3509a8054027SBarry Smith /*@
3510a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3511a8054027SBarry Smith 
3512c3339decSBarry Smith   Logically Collective
3513a8054027SBarry Smith 
3514a8054027SBarry Smith   Input Parameters:
3515f6dfbefdSBarry Smith + snes - the `SNES` context
3516d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35173b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3518a8054027SBarry Smith 
3519a8054027SBarry Smith   Options Database Keys:
3520420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35213d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3522420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35233d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3524a8054027SBarry Smith 
3525dc4c0fb0SBarry Smith   Level: intermediate
3526dc4c0fb0SBarry Smith 
3527420bcc1bSBarry Smith   Notes:
3528a8054027SBarry Smith   The default is 1
3529420bcc1bSBarry Smith 
3530f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3531d8e291bfSBarry Smith 
3532f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3533a8054027SBarry Smith 
35341cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3535f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3536a8054027SBarry Smith @*/
3537d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3538d71ae5a4SJacob Faibussowitsch {
3539a8054027SBarry Smith   PetscFunctionBegin;
35400700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35415f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35425f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3543c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3544a8054027SBarry Smith   snes->lagpreconditioner = lag;
35453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3546a8054027SBarry Smith }
3547a8054027SBarry Smith 
3548efd51863SBarry Smith /*@
3549f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3550efd51863SBarry Smith 
3551c3339decSBarry Smith   Logically Collective
3552efd51863SBarry Smith 
3553efd51863SBarry Smith   Input Parameters:
3554f6dfbefdSBarry Smith + snes  - the `SNES` context
3555efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3556efd51863SBarry Smith 
3557f6dfbefdSBarry Smith   Options Database Key:
355867b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3559efd51863SBarry Smith 
3560efd51863SBarry Smith   Level: intermediate
3561efd51863SBarry Smith 
3562f6dfbefdSBarry Smith   Note:
3563f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3564c0df2a02SJed Brown 
3565420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
3566420bcc1bSBarry Smith           `SNESetDM()`
3567efd51863SBarry Smith @*/
3568d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3569d71ae5a4SJacob Faibussowitsch {
3570efd51863SBarry Smith   PetscFunctionBegin;
3571efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3572efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3573efd51863SBarry Smith   snes->gridsequence = steps;
35743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3575efd51863SBarry Smith }
3576efd51863SBarry Smith 
3577fa19ca70SBarry Smith /*@
3578f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3579fa19ca70SBarry Smith 
3580c3339decSBarry Smith   Logically Collective
3581fa19ca70SBarry Smith 
3582fa19ca70SBarry Smith   Input Parameter:
3583f6dfbefdSBarry Smith . snes - the `SNES` context
3584fa19ca70SBarry Smith 
3585fa19ca70SBarry Smith   Output Parameter:
3586fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3587fa19ca70SBarry Smith 
3588fa19ca70SBarry Smith   Level: intermediate
3589fa19ca70SBarry Smith 
35901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3591fa19ca70SBarry Smith @*/
3592d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3593d71ae5a4SJacob Faibussowitsch {
3594fa19ca70SBarry Smith   PetscFunctionBegin;
3595fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3596fa19ca70SBarry Smith   *steps = snes->gridsequence;
35973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3598fa19ca70SBarry Smith }
3599fa19ca70SBarry Smith 
3600a8054027SBarry Smith /*@
3601f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3602a8054027SBarry Smith 
36033f9fe445SBarry Smith   Not Collective
3604a8054027SBarry Smith 
3605a8054027SBarry Smith   Input Parameter:
3606f6dfbefdSBarry Smith . snes - the `SNES` context
3607a8054027SBarry Smith 
3608a8054027SBarry Smith   Output Parameter:
3609a8054027SBarry 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
36103b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3611a8054027SBarry Smith 
3612dc4c0fb0SBarry Smith   Level: intermediate
3613dc4c0fb0SBarry Smith 
3614a8054027SBarry Smith   Notes:
3615a8054027SBarry Smith   The default is 1
3616f6dfbefdSBarry Smith 
3617a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3618a8054027SBarry Smith 
36191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3620a8054027SBarry Smith @*/
3621d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3622d71ae5a4SJacob Faibussowitsch {
3623a8054027SBarry Smith   PetscFunctionBegin;
36240700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3625a8054027SBarry Smith   *lag = snes->lagpreconditioner;
36263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3627a8054027SBarry Smith }
3628a8054027SBarry Smith 
3629e35cf81dSBarry Smith /*@
3630f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3631e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3632e35cf81dSBarry Smith 
3633c3339decSBarry Smith   Logically Collective
3634e35cf81dSBarry Smith 
3635e35cf81dSBarry Smith   Input Parameters:
3636f6dfbefdSBarry Smith + snes - the `SNES` context
3637e35cf81dSBarry 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
3638fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3639e35cf81dSBarry Smith 
3640e35cf81dSBarry Smith   Options Database Keys:
364179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36423d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
364379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36443d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3645e35cf81dSBarry Smith 
3646dc4c0fb0SBarry Smith   Level: intermediate
3647dc4c0fb0SBarry Smith 
3648e35cf81dSBarry Smith   Notes:
3649e35cf81dSBarry Smith   The default is 1
3650f6dfbefdSBarry Smith 
3651e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3652f6dfbefdSBarry Smith 
3653fe3ffe1eSBarry 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
3654fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3655e35cf81dSBarry Smith 
36561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3657e35cf81dSBarry Smith @*/
3658d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3659d71ae5a4SJacob Faibussowitsch {
3660e35cf81dSBarry Smith   PetscFunctionBegin;
36610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36625f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36635f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3664c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3665e35cf81dSBarry Smith   snes->lagjacobian = lag;
36663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3667e35cf81dSBarry Smith }
3668e35cf81dSBarry Smith 
3669e35cf81dSBarry Smith /*@
3670f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3671e35cf81dSBarry Smith 
36723f9fe445SBarry Smith   Not Collective
3673e35cf81dSBarry Smith 
3674e35cf81dSBarry Smith   Input Parameter:
3675f6dfbefdSBarry Smith . snes - the `SNES` context
3676e35cf81dSBarry Smith 
3677e35cf81dSBarry Smith   Output Parameter:
3678e35cf81dSBarry 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
3679e35cf81dSBarry Smith          the Jacobian is built etc.
3680e35cf81dSBarry Smith 
3681dc4c0fb0SBarry Smith   Level: intermediate
3682dc4c0fb0SBarry Smith 
3683e35cf81dSBarry Smith   Notes:
3684e35cf81dSBarry Smith   The default is 1
3685f6dfbefdSBarry Smith 
3686f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3687e35cf81dSBarry Smith 
36881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3689e35cf81dSBarry Smith 
3690e35cf81dSBarry Smith @*/
3691d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3692d71ae5a4SJacob Faibussowitsch {
3693e35cf81dSBarry Smith   PetscFunctionBegin;
36940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3695e35cf81dSBarry Smith   *lag = snes->lagjacobian;
36963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3697e35cf81dSBarry Smith }
3698e35cf81dSBarry Smith 
369937ec4e1aSPeter Brune /*@
3700f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
370137ec4e1aSPeter Brune 
3702c3339decSBarry Smith   Logically collective
370337ec4e1aSPeter Brune 
3704d8d19677SJose E. Roman   Input Parameters:
3705f6dfbefdSBarry Smith + snes - the `SNES` context
37069d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
370737ec4e1aSPeter Brune 
370837ec4e1aSPeter Brune   Options Database Keys:
370979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37103d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
371179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37123d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37133d5a8a6aSBarry Smith 
3714dc4c0fb0SBarry Smith   Level: advanced
3715dc4c0fb0SBarry Smith 
371695452b02SPatrick Sanan   Notes:
3717420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3718f6dfbefdSBarry Smith 
371995452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
372037ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
372137ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
372237ec4e1aSPeter Brune 
372342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
372437ec4e1aSPeter Brune @*/
3725d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3726d71ae5a4SJacob Faibussowitsch {
372737ec4e1aSPeter Brune   PetscFunctionBegin;
372837ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
372937ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
373037ec4e1aSPeter Brune   snes->lagjac_persist = flg;
37313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
373237ec4e1aSPeter Brune }
373337ec4e1aSPeter Brune 
373437ec4e1aSPeter Brune /*@
3735d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
373637ec4e1aSPeter Brune 
3737c3339decSBarry Smith   Logically Collective
373837ec4e1aSPeter Brune 
3739d8d19677SJose E. Roman   Input Parameters:
3740f6dfbefdSBarry Smith + snes - the `SNES` context
37419d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
374237ec4e1aSPeter Brune 
374337ec4e1aSPeter Brune   Options Database Keys:
374479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37453d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
374679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37473d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
374837ec4e1aSPeter Brune 
3749dc4c0fb0SBarry Smith   Level: developer
3750dc4c0fb0SBarry Smith 
375195452b02SPatrick Sanan   Notes:
3752420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3753f6dfbefdSBarry Smith 
375495452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
375537ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
375637ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
375737ec4e1aSPeter Brune 
37581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
375937ec4e1aSPeter Brune @*/
3760d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3761d71ae5a4SJacob Faibussowitsch {
376237ec4e1aSPeter Brune   PetscFunctionBegin;
376337ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
376437ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
376537ec4e1aSPeter Brune   snes->lagpre_persist = flg;
37663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
376737ec4e1aSPeter Brune }
376837ec4e1aSPeter Brune 
37699b94acceSBarry Smith /*@
3770f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3771be5caee7SBarry Smith 
3772c3339decSBarry Smith   Logically Collective
3773be5caee7SBarry Smith 
3774be5caee7SBarry Smith   Input Parameters:
3775f6dfbefdSBarry Smith + snes  - the `SNES` context
3776f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3777be5caee7SBarry Smith 
3778f6dfbefdSBarry Smith   Options Database Key:
3779be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3780be5caee7SBarry Smith 
3781dc4c0fb0SBarry Smith   Level: intermediate
3782dc4c0fb0SBarry Smith 
3783f6dfbefdSBarry Smith   Note:
3784f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3785be5caee7SBarry Smith 
37861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3787be5caee7SBarry Smith @*/
3788d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3789d71ae5a4SJacob Faibussowitsch {
3790be5caee7SBarry Smith   PetscFunctionBegin;
3791be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3792be5caee7SBarry Smith   snes->forceiteration = force;
37933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3794be5caee7SBarry Smith }
3795be5caee7SBarry Smith 
379685216dc7SFande Kong /*@
3797f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
379885216dc7SFande Kong 
3799c3339decSBarry Smith   Logically Collective
380085216dc7SFande Kong 
38012fe279fdSBarry Smith   Input Parameter:
3802f6dfbefdSBarry Smith . snes - the `SNES` context
380385216dc7SFande Kong 
380485216dc7SFande Kong   Output Parameter:
3805dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
380685216dc7SFande Kong 
380706dd6b0eSSatish Balay   Level: intermediate
380806dd6b0eSSatish Balay 
38091cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
381085216dc7SFande Kong @*/
3811d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3812d71ae5a4SJacob Faibussowitsch {
381385216dc7SFande Kong   PetscFunctionBegin;
381485216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
381585216dc7SFande Kong   *force = snes->forceiteration;
38163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
381785216dc7SFande Kong }
3818be5caee7SBarry Smith 
3819be5caee7SBarry Smith /*@
3820f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
38219b94acceSBarry Smith 
3822c3339decSBarry Smith   Logically Collective
3823c7afd0dbSLois Curfman McInnes 
38249b94acceSBarry Smith   Input Parameters:
3825f6dfbefdSBarry Smith + snes   - the `SNES` context
382670441072SBarry Smith . abstol - absolute convergence tolerance
382733174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
38285358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3829f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
3830*77e5a1f9SBarry Smith - maxf   - maximum number of function evaluations (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3831fee21e36SBarry Smith 
383233174efeSLois Curfman McInnes   Options Database Keys:
3833*77e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
3834*77e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
3835*77e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
3836*77e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
3837*77e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
38389b94acceSBarry Smith 
383936851e7fSLois Curfman McInnes   Level: intermediate
384036851e7fSLois Curfman McInnes 
3841*77e5a1f9SBarry Smith   Note:
3842*77e5a1f9SBarry Smith   All parameters must be non-negative
3843*77e5a1f9SBarry Smith 
3844*77e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
3845*77e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
3846*77e5a1f9SBarry Smith 
3847*77e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
3848*77e5a1f9SBarry Smith 
3849*77e5a1f9SBarry Smith   Fortran Note:
3850*77e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
3851*77e5a1f9SBarry Smith 
385200677de2SStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
38539b94acceSBarry Smith @*/
3854d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3855d71ae5a4SJacob Faibussowitsch {
38563a40ed3dSBarry Smith   PetscFunctionBegin;
38570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3858c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3859c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3860c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3861c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3862c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3863c5eb9154SBarry Smith 
3864*77e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
3865*77e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
3866*77e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
38675f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3868ab54825eSJed Brown     snes->abstol = abstol;
3869ab54825eSJed Brown   }
3870*77e5a1f9SBarry Smith 
3871*77e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
3872*77e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
3873*77e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
38745f80ce2aSJacob 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);
3875ab54825eSJed Brown     snes->rtol = rtol;
3876ab54825eSJed Brown   }
3877*77e5a1f9SBarry Smith 
3878*77e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
3879*77e5a1f9SBarry Smith     snes->stol = snes->default_stol;
3880*77e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
38815f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3882c60f73f4SPeter Brune     snes->stol = stol;
3883ab54825eSJed Brown   }
3884*77e5a1f9SBarry Smith 
3885*77e5a1f9SBarry Smith   if (maxit == (PetscInt)PETSC_DETERMINE) {
3886*77e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
3887*77e5a1f9SBarry Smith   } else if (maxit == (PetscInt)PETSC_UNLIMITED) {
3888*77e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
3889*77e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
389063a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3891ab54825eSJed Brown     snes->max_its = maxit;
3892ab54825eSJed Brown   }
3893*77e5a1f9SBarry Smith 
3894*77e5a1f9SBarry Smith   if (maxf == (PetscInt)PETSC_DETERMINE) {
3895*77e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
3896*77e5a1f9SBarry Smith   } else if (maxf == (PetscInt)PETSC_UNLIMITED || maxf == -1) {
3897*77e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
3898*77e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
3899*77e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3900ab54825eSJed Brown     snes->max_funcs = maxf;
3901ab54825eSJed Brown   }
39023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39039b94acceSBarry Smith }
39049b94acceSBarry Smith 
3905e4d06f11SPatrick Farrell /*@
3906f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3907e4d06f11SPatrick Farrell 
3908c3339decSBarry Smith   Logically Collective
3909e4d06f11SPatrick Farrell 
3910e4d06f11SPatrick Farrell   Input Parameters:
3911f6dfbefdSBarry Smith + snes   - the `SNES` context
3912*77e5a1f9SBarry Smith - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test, default is 1e4
3913e4d06f11SPatrick Farrell 
3914f6dfbefdSBarry Smith   Options Database Key:
3915dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3916e4d06f11SPatrick Farrell 
3917e4d06f11SPatrick Farrell   Level: intermediate
3918e4d06f11SPatrick Farrell 
3919*77e5a1f9SBarry Smith   Notes:
3920*77e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
3921e5cd489fSStefano Zampini 
3922*77e5a1f9SBarry Smith   Fortran Note:
3923*77e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
3924*77e5a1f9SBarry Smith 
3925*77e5a1f9SBarry Smith   Developer Note:
3926*77e5a1f9SBarry Smith   Also supports the deprecated -1 to indicate no bound on the growth of the residual
3927*77e5a1f9SBarry Smith 
3928*77e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
3929e4d06f11SPatrick Farrell @*/
3930d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3931d71ae5a4SJacob Faibussowitsch {
3932e4d06f11SPatrick Farrell   PetscFunctionBegin;
3933e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3934e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3935*77e5a1f9SBarry Smith 
3936*77e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
3937*77e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
3938*77e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
3939*77e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
3940*77e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
3941*77e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
3942*77e5a1f9SBarry Smith     snes->divtol = divtol;
3943*77e5a1f9SBarry Smith   }
39443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3945e4d06f11SPatrick Farrell }
3946e4d06f11SPatrick Farrell 
39479b94acceSBarry Smith /*@
394833174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
394933174efeSLois Curfman McInnes 
3950c7afd0dbSLois Curfman McInnes   Not Collective
3951c7afd0dbSLois Curfman McInnes 
3952*77e5a1f9SBarry Smith   Input Parameter:
3953*77e5a1f9SBarry Smith . snes - the `SNES` context
3954*77e5a1f9SBarry Smith 
3955*77e5a1f9SBarry Smith   Output Parameters:
3956*77e5a1f9SBarry Smith + atol  - absolute convergence tolerance
395733174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
3958*77e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
395933174efeSLois Curfman McInnes . maxit - maximum number of iterations
3960*77e5a1f9SBarry Smith - maxf  - maximum number of function evaluations, `PETSC_UNLIMITED` indicates no bound
3961fee21e36SBarry Smith 
396236851e7fSLois Curfman McInnes   Level: intermediate
396336851e7fSLois Curfman McInnes 
3964dc4c0fb0SBarry Smith   Note:
3965dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3966dc4c0fb0SBarry Smith 
39671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
396833174efeSLois Curfman McInnes @*/
3969d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3970d71ae5a4SJacob Faibussowitsch {
39713a40ed3dSBarry Smith   PetscFunctionBegin;
39720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
397385385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
397433174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3975c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
397633174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
397733174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
39783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
397933174efeSLois Curfman McInnes }
398033174efeSLois Curfman McInnes 
3981e4d06f11SPatrick Farrell /*@
3982e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3983e4d06f11SPatrick Farrell 
3984e4d06f11SPatrick Farrell   Not Collective
3985e4d06f11SPatrick Farrell 
3986e4d06f11SPatrick Farrell   Input Parameters:
3987f6dfbefdSBarry Smith + snes   - the `SNES` context
3988e4d06f11SPatrick Farrell - divtol - divergence tolerance
3989e4d06f11SPatrick Farrell 
3990e4d06f11SPatrick Farrell   Level: intermediate
3991e4d06f11SPatrick Farrell 
39921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3993e4d06f11SPatrick Farrell @*/
3994d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3995d71ae5a4SJacob Faibussowitsch {
3996e4d06f11SPatrick Farrell   PetscFunctionBegin;
3997e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3998e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
39993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4000e4d06f11SPatrick Farrell }
4001e4d06f11SPatrick Farrell 
400233174efeSLois Curfman McInnes /*@
40039b94acceSBarry Smith   SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
40049b94acceSBarry Smith 
4005c3339decSBarry Smith   Logically Collective
4006fee21e36SBarry Smith 
4007c7afd0dbSLois Curfman McInnes   Input Parameters:
4008f6dfbefdSBarry Smith + snes - the `SNES` context
4009*77e5a1f9SBarry Smith - tol  - tolerance, must be non-negative
4010c7afd0dbSLois Curfman McInnes 
40119b94acceSBarry Smith   Options Database Key:
40124a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol
40139b94acceSBarry Smith 
401436851e7fSLois Curfman McInnes   Level: intermediate
401536851e7fSLois Curfman McInnes 
4016*77e5a1f9SBarry Smith   Note:
4017*77e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value for the given `SNES`. The default value is the value in the object when its type is set
4018*77e5a1f9SBarry Smith 
4019*77e5a1f9SBarry Smith   Fortran Note:
4020*77e5a1f9SBarry Smith   Use `PETSC_DETERMINE_REAL`
4021*77e5a1f9SBarry Smith 
40229bcc50f1SBarry Smith   Developer Note:
4023*77e5a1f9SBarry Smith   Should be named `SNESTrustRegionSetTolerance()`
40249bcc50f1SBarry Smith 
40251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
40269b94acceSBarry Smith @*/
4027d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
4028d71ae5a4SJacob Faibussowitsch {
40293a40ed3dSBarry Smith   PetscFunctionBegin;
40300700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4031c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
4032*77e5a1f9SBarry Smith   if (tol == (PetscReal)PETSC_DETERMINE) {
4033*77e5a1f9SBarry Smith     snes->deltatol = snes->default_deltatol;
4034*77e5a1f9SBarry Smith   } else if (tol > 0) snes->deltatol = tol;
4035*77e5a1f9SBarry Smith   else SETERRQ(PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot set negative trust region tolerance");
40363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40379b94acceSBarry Smith }
40389b94acceSBarry Smith 
40396ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40406ba87a44SLisandro Dalcin 
4041d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4042d71ae5a4SJacob Faibussowitsch {
4043b271bb04SBarry Smith   PetscDrawLG      lg;
4044b271bb04SBarry Smith   PetscReal        x, y, per;
4045b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4046b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4047b271bb04SBarry Smith   PetscDraw        draw;
4048b271bb04SBarry Smith 
4049459f5d12SBarry Smith   PetscFunctionBegin;
40504d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40519566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40529566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40539566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40549566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4055b271bb04SBarry Smith   x = (PetscReal)n;
405677b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
405794c9c6d3SKarl Rupp   else y = -15.0;
40589566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40596934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40609566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40619566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4062b271bb04SBarry Smith   }
4063b271bb04SBarry Smith 
40649566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
40659566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40669566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4067aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
40689566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4069b271bb04SBarry Smith   x = (PetscReal)n;
4070b271bb04SBarry Smith   y = 100.0 * per;
40719566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40726934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40739566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40749566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4075b271bb04SBarry Smith   }
4076b271bb04SBarry Smith 
40779566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
40789371c9d4SSatish Balay   if (!n) {
40799371c9d4SSatish Balay     prev = rnorm;
40809371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
40819371c9d4SSatish Balay   }
40829566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40839566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4084b271bb04SBarry Smith   x = (PetscReal)n;
4085b271bb04SBarry Smith   y = (prev - rnorm) / prev;
40869566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40876934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40889566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40899566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4090b271bb04SBarry Smith   }
4091b271bb04SBarry Smith 
40929566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
40939566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40949566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40959566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4096b271bb04SBarry Smith   x = (PetscReal)n;
4097b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4098b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
40999566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4100b271bb04SBarry Smith   }
41016934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
41029566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
41039566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4104b271bb04SBarry Smith   }
4105b271bb04SBarry Smith   prev = rnorm;
41063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4107b271bb04SBarry Smith }
4108b271bb04SBarry Smith 
4109228d79bcSJed Brown /*@
41102d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41112d157150SStefano Zampini 
41122d157150SStefano Zampini   Collective
41132d157150SStefano Zampini 
41142d157150SStefano Zampini   Input Parameters:
41152d157150SStefano Zampini + snes  - the `SNES` context
41162d157150SStefano Zampini . it    - current iteration
41172d157150SStefano Zampini . xnorm - 2-norm of current iterate
41182d157150SStefano Zampini . snorm - 2-norm of current step
41192d157150SStefano Zampini - fnorm - 2-norm of function
41202d157150SStefano Zampini 
41212d157150SStefano Zampini   Level: developer
41222d157150SStefano Zampini 
41232d157150SStefano Zampini   Note:
4124420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41252d157150SStefano Zampini   It does not typically need to be called by the user.
41262d157150SStefano Zampini 
4127be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
41282d157150SStefano Zampini @*/
41292d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41302d157150SStefano Zampini {
41312d157150SStefano Zampini   PetscFunctionBegin;
41322d157150SStefano Zampini   if (!snes->reason) {
41332d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41342d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41352d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41362d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41372d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41382d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41392d157150SStefano Zampini     }
41402d157150SStefano Zampini   }
41412d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41422d157150SStefano Zampini }
41432d157150SStefano Zampini 
41442d157150SStefano Zampini /*@
4145228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
4146228d79bcSJed Brown 
4147c3339decSBarry Smith   Collective
4148228d79bcSJed Brown 
4149228d79bcSJed Brown   Input Parameters:
4150f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
4151228d79bcSJed Brown . iter  - iteration number
4152228d79bcSJed Brown - rnorm - relative norm of the residual
4153228d79bcSJed Brown 
4154dc4c0fb0SBarry Smith   Level: developer
4155dc4c0fb0SBarry Smith 
4156f6dfbefdSBarry Smith   Note:
4157420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4158228d79bcSJed Brown   It does not typically need to be called by the user.
4159228d79bcSJed Brown 
41601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4161228d79bcSJed Brown @*/
4162d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4163d71ae5a4SJacob Faibussowitsch {
41647a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
41657a03ce2fSLisandro Dalcin 
41667a03ce2fSLisandro Dalcin   PetscFunctionBegin;
41675f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
41689566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
416948a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
41709566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
41713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41727a03ce2fSLisandro Dalcin }
41737a03ce2fSLisandro Dalcin 
41749b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
41759b94acceSBarry Smith 
4176bf388a1fSBarry Smith /*MC
4177f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4178bf388a1fSBarry Smith 
4179bf388a1fSBarry Smith      Synopsis:
4180aaa7dc30SBarry Smith      #include <petscsnes.h>
418137fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4182bf388a1fSBarry Smith 
4183c3339decSBarry Smith      Collective
41841843f636SBarry Smith 
41851843f636SBarry Smith     Input Parameters:
4186f6dfbefdSBarry Smith +    snes - the `SNES` context
4187bf388a1fSBarry Smith .    its - iteration number
4188bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4189bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4190bf388a1fSBarry Smith 
4191878cb397SSatish Balay    Level: advanced
4192878cb397SSatish Balay 
41931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4194bf388a1fSBarry Smith M*/
4195bf388a1fSBarry Smith 
41969b94acceSBarry Smith /*@C
4197a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
41989b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
41999b94acceSBarry Smith   progress.
42009b94acceSBarry Smith 
4201c3339decSBarry Smith   Logically Collective
4202fee21e36SBarry Smith 
4203c7afd0dbSLois Curfman McInnes   Input Parameters:
4204f6dfbefdSBarry Smith + snes           - the `SNES` context
420520f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4206420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4207dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
42089b94acceSBarry Smith 
42099665c990SLois Curfman McInnes   Options Database Keys:
4210f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4211798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4212dc4c0fb0SBarry 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
4213c7afd0dbSLois Curfman McInnes                                 the options database.
42149665c990SLois Curfman McInnes 
4215dc4c0fb0SBarry Smith   Level: intermediate
4216dc4c0fb0SBarry Smith 
4217f6dfbefdSBarry Smith   Note:
42186bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4219f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42206bc08f3fSLois Curfman McInnes   order in which they were set.
4221639f9d9dSBarry Smith 
4222420bcc1bSBarry Smith   Fortran Note:
4223f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4224025f1a04SBarry Smith 
42251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
42269b94acceSBarry Smith @*/
4227d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4228d71ae5a4SJacob Faibussowitsch {
4229b90d0a6eSBarry Smith   PetscInt  i;
423078064530SBarry Smith   PetscBool identical;
4231b90d0a6eSBarry Smith 
42323a40ed3dSBarry Smith   PetscFunctionBegin;
42330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4234b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
42359566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42363ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4237649052a6SBarry Smith   }
42385f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42396e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4240b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4241639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
42423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42439b94acceSBarry Smith }
42449b94acceSBarry Smith 
4245a278d85bSSatish Balay /*@
4246f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42475cd90555SBarry Smith 
4248c3339decSBarry Smith   Logically Collective
4249c7afd0dbSLois Curfman McInnes 
42502fe279fdSBarry Smith   Input Parameter:
4251f6dfbefdSBarry Smith . snes - the `SNES` context
42525cd90555SBarry Smith 
42531a480d89SAdministrator   Options Database Key:
4254a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4255dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4256c7afd0dbSLois Curfman McInnes     set via the options database
42575cd90555SBarry Smith 
4258dc4c0fb0SBarry Smith   Level: intermediate
4259dc4c0fb0SBarry Smith 
4260f6dfbefdSBarry Smith   Note:
4261f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
42625cd90555SBarry Smith 
42631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
42645cd90555SBarry Smith @*/
4265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4266d71ae5a4SJacob Faibussowitsch {
4267d952e501SBarry Smith   PetscInt i;
4268d952e501SBarry Smith 
42695cd90555SBarry Smith   PetscFunctionBegin;
42700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4271d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
427248a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4273d952e501SBarry Smith   }
42745cd90555SBarry Smith   snes->numbermonitors = 0;
42753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42765cd90555SBarry Smith }
42775cd90555SBarry Smith 
4278bf388a1fSBarry Smith /*MC
4279bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4280bf388a1fSBarry Smith 
4281bf388a1fSBarry Smith      Synopsis:
4282aaa7dc30SBarry Smith      #include <petscsnes.h>
428337fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4284bf388a1fSBarry Smith 
4285c3339decSBarry Smith      Collective
42861843f636SBarry Smith 
42871843f636SBarry Smith     Input Parameters:
4288f6dfbefdSBarry Smith +    snes - the `SNES` context
4289bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4290bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4291bf388a1fSBarry Smith .    gnorm - 2-norm of current step
42921843f636SBarry Smith .    f - 2-norm of function
42931843f636SBarry Smith -    cctx - [optional] convergence context
42941843f636SBarry Smith 
42951843f636SBarry Smith     Output Parameter:
42961843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4297bf388a1fSBarry Smith 
4298878cb397SSatish Balay    Level: intermediate
4299bf388a1fSBarry Smith 
43001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4301bf388a1fSBarry Smith M*/
4302bf388a1fSBarry Smith 
43039b94acceSBarry Smith /*@C
43049b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
43059b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
43069b94acceSBarry Smith 
4307c3339decSBarry Smith   Logically Collective
4308fee21e36SBarry Smith 
4309c7afd0dbSLois Curfman McInnes   Input Parameters:
4310f6dfbefdSBarry Smith + snes                        - the `SNES` context
4311e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4312dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4313dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43149b94acceSBarry Smith 
431536851e7fSLois Curfman McInnes   Level: advanced
431636851e7fSLois Curfman McInnes 
43171cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43189b94acceSBarry Smith @*/
4319d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4320d71ae5a4SJacob Faibussowitsch {
43213a40ed3dSBarry Smith   PetscFunctionBegin;
43220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4323e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
43241baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4325bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43267f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
432785385478SLisandro Dalcin   snes->cnvP                  = cctx;
43283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43299b94acceSBarry Smith }
43309b94acceSBarry Smith 
433152baeb72SSatish Balay /*@
4332f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4333184914b5SBarry Smith 
4334184914b5SBarry Smith   Not Collective
4335184914b5SBarry Smith 
4336184914b5SBarry Smith   Input Parameter:
4337f6dfbefdSBarry Smith . snes - the `SNES` context
4338184914b5SBarry Smith 
4339184914b5SBarry Smith   Output Parameter:
4340f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4341184914b5SBarry Smith 
4342f6dfbefdSBarry Smith   Options Database Key:
43436a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43446a4d7782SBarry Smith 
4345184914b5SBarry Smith   Level: intermediate
4346184914b5SBarry Smith 
4347f6dfbefdSBarry Smith   Note:
4348f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4349184914b5SBarry Smith 
43501cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4351184914b5SBarry Smith @*/
4352d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4353d71ae5a4SJacob Faibussowitsch {
4354184914b5SBarry Smith   PetscFunctionBegin;
43550700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43564f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4357184914b5SBarry Smith   *reason = snes->reason;
43583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4359184914b5SBarry Smith }
4360184914b5SBarry Smith 
4361c4421ceaSFande Kong /*@C
4362f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4363c4421ceaSFande Kong 
4364c4421ceaSFande Kong   Not Collective
4365c4421ceaSFande Kong 
4366c4421ceaSFande Kong   Input Parameter:
4367f6dfbefdSBarry Smith . snes - the `SNES` context
4368c4421ceaSFande Kong 
4369c4421ceaSFande Kong   Output Parameter:
4370dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4371c4421ceaSFande Kong 
437299c90e12SSatish Balay   Level: beginner
4373c4421ceaSFande Kong 
43741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4375c4421ceaSFande Kong @*/
4376d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4377d71ae5a4SJacob Faibussowitsch {
4378c4421ceaSFande Kong   PetscFunctionBegin;
4379c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43804f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4381c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
43823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4383c4421ceaSFande Kong }
4384c4421ceaSFande Kong 
438533866048SMatthew G. Knepley /*@
4386f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
438733866048SMatthew G. Knepley 
438833866048SMatthew G. Knepley   Not Collective
438933866048SMatthew G. Knepley 
439033866048SMatthew G. Knepley   Input Parameters:
4391f6dfbefdSBarry Smith + snes   - the `SNES` context
4392f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
439333866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
439433866048SMatthew G. Knepley 
4395f6dfbefdSBarry Smith   Level: developer
4396f6dfbefdSBarry Smith 
4397420bcc1bSBarry Smith   Developer Note:
4398f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
439933866048SMatthew G. Knepley 
44001cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
440133866048SMatthew G. Knepley @*/
4402d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4403d71ae5a4SJacob Faibussowitsch {
440433866048SMatthew G. Knepley   PetscFunctionBegin;
440533866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44065f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
440733866048SMatthew G. Knepley   snes->reason = reason;
44083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
440933866048SMatthew G. Knepley }
441033866048SMatthew G. Knepley 
4411c9005455SLois Curfman McInnes /*@
4412420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4413c9005455SLois Curfman McInnes 
4414c3339decSBarry Smith   Logically Collective
4415fee21e36SBarry Smith 
4416c7afd0dbSLois Curfman McInnes   Input Parameters:
4417f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44188c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4419cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4420420bcc1bSBarry Smith . na    - size of `a` and `its`
4421f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4422758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4423c7afd0dbSLois Curfman McInnes 
4424dc4c0fb0SBarry Smith   Level: intermediate
4425dc4c0fb0SBarry Smith 
4426308dcc3eSBarry Smith   Notes:
4427*77e5a1f9SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` then a
4428*77e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4429308dcc3eSBarry Smith 
4430c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4431c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4432c9005455SLois Curfman McInnes   during the section of code that is being timed.
4433c9005455SLois Curfman McInnes 
4434420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4435420bcc1bSBarry Smith 
44361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4437c9005455SLois Curfman McInnes @*/
4438d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4439d71ae5a4SJacob Faibussowitsch {
44403a40ed3dSBarry Smith   PetscFunctionBegin;
44410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44424f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44434f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44447a1ec6d4SBarry Smith   if (!a) {
4445*77e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44469566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4447071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4448308dcc3eSBarry Smith   }
4449c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4450758f92a0SBarry Smith   snes->conv_hist_its   = its;
4451115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4452a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4453758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4455758f92a0SBarry Smith }
4456758f92a0SBarry Smith 
4457d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4458c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4459c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
446099e0435eSBarry Smith 
4461d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4462d71ae5a4SJacob Faibussowitsch {
4463308dcc3eSBarry Smith   mxArray   *mat;
4464308dcc3eSBarry Smith   PetscInt   i;
4465308dcc3eSBarry Smith   PetscReal *ar;
4466308dcc3eSBarry Smith 
4467308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4468308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4469f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
447011cc89d2SBarry Smith   return mat;
4471308dcc3eSBarry Smith }
4472308dcc3eSBarry Smith #endif
4473308dcc3eSBarry Smith 
44740c4c9dddSBarry Smith /*@C
4475420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4476758f92a0SBarry Smith 
44773f9fe445SBarry Smith   Not Collective
4478758f92a0SBarry Smith 
4479758f92a0SBarry Smith   Input Parameter:
4480f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4481758f92a0SBarry Smith 
4482758f92a0SBarry Smith   Output Parameters:
4483f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4484758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4485758f92a0SBarry Smith          negative if not converged) for each solve.
448620f4b53cSBarry Smith - na  - size of `a` and `its`
4487758f92a0SBarry Smith 
4488dc4c0fb0SBarry Smith   Level: intermediate
4489dc4c0fb0SBarry Smith 
449020f4b53cSBarry Smith   Note:
449120f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
449220f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
449320f4b53cSBarry Smith   during the section of code that is being timed.
449420f4b53cSBarry Smith 
4495420bcc1bSBarry Smith   Fortran Note:
4496758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4497dc4c0fb0SBarry Smith .vb
4498dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4499dc4c0fb0SBarry Smith .ve
4500758f92a0SBarry Smith 
45011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4502758f92a0SBarry Smith @*/
4503d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4504d71ae5a4SJacob Faibussowitsch {
4505758f92a0SBarry Smith   PetscFunctionBegin;
45060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4507758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4508758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4509115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
45103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4511c9005455SLois Curfman McInnes }
4512c9005455SLois Curfman McInnes 
4513ac226902SBarry Smith /*@C
451476b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4515eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
451653e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
451753e5d35bSStefano Zampini   evaluation.
451876b2cf59SMatthew Knepley 
4519c3339decSBarry Smith   Logically Collective
452076b2cf59SMatthew Knepley 
452176b2cf59SMatthew Knepley   Input Parameters:
4522a2b725a8SWilliam Gropp + snes - The nonlinear solver context
452353e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
452476b2cf59SMatthew Knepley 
4525fe97e370SBarry Smith   Level: advanced
4526fe97e370SBarry Smith 
4527420bcc1bSBarry Smith   Notes:
4528f6dfbefdSBarry 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
4529f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
453053e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
453153e5d35bSStefano Zampini   right before the direction step is computed.
453253e5d35bSStefano Zampini   Users are free to modify the current residual vector,
453353e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
453453e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
453553e5d35bSStefano Zampini   vectors.
453676b2cf59SMatthew Knepley 
4537aaa8cc7dSPierre 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.
45386b7fb656SBarry Smith 
4539e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
454053e5d35bSStefano Zampini          `SNESMonitorSet()`
454176b2cf59SMatthew Knepley @*/
454253e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4543d71ae5a4SJacob Faibussowitsch {
454476b2cf59SMatthew Knepley   PetscFunctionBegin;
45450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4546e7788613SBarry Smith   snes->ops->update = func;
45473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
454876b2cf59SMatthew Knepley }
454976b2cf59SMatthew Knepley 
4550ffeef943SBarry Smith /*@
4551f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
45522a359c20SBarry Smith 
4553c3339decSBarry Smith   Collective
45542a359c20SBarry Smith 
4555e4094ef1SJacob Faibussowitsch   Input Parameters:
4556f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
45572a359c20SBarry Smith - viewer - the viewer to display the reason
45582a359c20SBarry Smith 
45592a359c20SBarry Smith   Options Database Keys:
4560ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4561ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4562eafd5ff0SAlex Lindsay 
4563420bcc1bSBarry Smith   Level: beginner
4564420bcc1bSBarry Smith 
4565f6dfbefdSBarry Smith   Note:
4566f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4567f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
45682a359c20SBarry Smith 
45691cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4570f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4571f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4572db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
45732a359c20SBarry Smith @*/
4574d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4575d71ae5a4SJacob Faibussowitsch {
457675cca76cSMatthew G. Knepley   PetscViewerFormat format;
45772a359c20SBarry Smith   PetscBool         isAscii;
45782a359c20SBarry Smith 
45792a359c20SBarry Smith   PetscFunctionBegin;
458019a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
45819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
45822a359c20SBarry Smith   if (isAscii) {
45839566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
458465bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
458575cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
458675cca76cSMatthew G. Knepley       DM       dm;
458775cca76cSMatthew G. Knepley       Vec      u;
458875cca76cSMatthew G. Knepley       PetscDS  prob;
458975cca76cSMatthew G. Knepley       PetscInt Nf, f;
459095cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
459195cbbfd3SMatthew G. Knepley       void    **exactCtx;
459275cca76cSMatthew G. Knepley       PetscReal error;
459375cca76cSMatthew G. Knepley 
45949566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
45959566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
45969566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
45979566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
45989566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
45999566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
46009566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
46019566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
46029566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
460363a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
460475cca76cSMatthew G. Knepley     }
4605eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
46062a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
460763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46082a359c20SBarry Smith       } else {
460963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46102a359c20SBarry Smith       }
4611eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
46122a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
461363a3b9bcSJacob 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));
46142a359c20SBarry Smith       } else {
461563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46162a359c20SBarry Smith       }
46172a359c20SBarry Smith     }
461865bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46192a359c20SBarry Smith   }
46203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46212a359c20SBarry Smith }
46222a359c20SBarry Smith 
4623c4421ceaSFande Kong /*@C
4624c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4625aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4626c4421ceaSFande Kong 
4627c3339decSBarry Smith   Logically Collective
4628c4421ceaSFande Kong 
4629c4421ceaSFande Kong   Input Parameters:
4630f6dfbefdSBarry Smith + snes              - the `SNES` context
4631420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4632420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4633420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`)
4634420bcc1bSBarry Smith 
4635420bcc1bSBarry Smith   Calling sequence of `f`:
4636420bcc1bSBarry Smith + snes - the `SNES` context
4637420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function
4638420bcc1bSBarry Smith 
4639420bcc1bSBarry Smith   Calling sequence of `reasonviewerdestroy`:
4640420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function
4641c4421ceaSFande Kong 
4642c4421ceaSFande Kong   Options Database Keys:
4643f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4644420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4645420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4646c4421ceaSFande Kong 
4647dc4c0fb0SBarry Smith   Level: intermediate
4648dc4c0fb0SBarry Smith 
4649f6dfbefdSBarry Smith   Note:
4650c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4651f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4652c4421ceaSFande Kong   order in which they were set.
4653c4421ceaSFande Kong 
46541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4655c4421ceaSFande Kong @*/
4656420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx))
4657d71ae5a4SJacob Faibussowitsch {
4658c4421ceaSFande Kong   PetscInt  i;
4659c4421ceaSFande Kong   PetscBool identical;
4660c4421ceaSFande Kong 
4661c4421ceaSFande Kong   PetscFunctionBegin;
4662c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4663c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
46649566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
46653ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4666c4421ceaSFande Kong   }
46675f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4668c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4669c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4670c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
46713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4672c4421ceaSFande Kong }
4673c4421ceaSFande Kong 
467491f3e32bSBarry Smith /*@
4675420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4676c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
46772a359c20SBarry Smith 
4678c3339decSBarry Smith   Collective
46792a359c20SBarry Smith 
46802fe279fdSBarry Smith   Input Parameter:
4681f6dfbefdSBarry Smith . snes - the `SNES` object
46822a359c20SBarry Smith 
4683f6dfbefdSBarry Smith   Level: advanced
46842a359c20SBarry Smith 
46851cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4686f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
46872a359c20SBarry Smith @*/
4688d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4689d71ae5a4SJacob Faibussowitsch {
46902a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
46912a359c20SBarry Smith 
46922a359c20SBarry Smith   PetscFunctionBegin;
46933ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
46942a359c20SBarry Smith   incall = PETSC_TRUE;
4695c4421ceaSFande Kong 
4696c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
469736d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4698c4421ceaSFande Kong 
4699c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
470036d43d94SBarry Smith   if (snes->convergedreasonviewer) {
470136d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
470236d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
470336d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
47042a359c20SBarry Smith   }
47052a359c20SBarry Smith   incall = PETSC_FALSE;
47063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47072a359c20SBarry Smith }
47082a359c20SBarry Smith 
4709487a658cSBarry Smith /*@
4710f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
47119b94acceSBarry Smith 
4712c3339decSBarry Smith   Collective
4713c7afd0dbSLois Curfman McInnes 
4714b2002411SLois Curfman McInnes   Input Parameters:
4715f6dfbefdSBarry Smith + snes - the `SNES` context
4716dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
471785385478SLisandro Dalcin - x    - the solution vector.
47189b94acceSBarry Smith 
4719dc4c0fb0SBarry Smith   Level: beginner
4720dc4c0fb0SBarry Smith 
4721f6dfbefdSBarry Smith   Note:
4722420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4723420bcc1bSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
47248ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4725f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
47268ddd3da0SLois Curfman McInnes 
47271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4728db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4729420bcc1bSBarry Smith           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
47309b94acceSBarry Smith @*/
4731d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4732d71ae5a4SJacob Faibussowitsch {
4733ace3abfcSBarry Smith   PetscBool flg;
4734efd51863SBarry Smith   PetscInt  grid;
47350298fd71SBarry Smith   Vec       xcreated = NULL;
4736caa4e7f2SJed Brown   DM        dm;
4737052efed2SBarry Smith 
47383a40ed3dSBarry Smith   PetscFunctionBegin;
47390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4740a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4741a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47420700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
474385385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
474485385478SLisandro Dalcin 
474534b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
474606fc46c8SMatthew G. Knepley   {
474706fc46c8SMatthew G. Knepley     PetscViewer       viewer;
474806fc46c8SMatthew G. Knepley     PetscViewerFormat format;
47497c88af5aSMatthew G. Knepley     PetscInt          num;
475006fc46c8SMatthew G. Knepley     PetscBool         flg;
475106fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
475206fc46c8SMatthew G. Knepley 
475306fc46c8SMatthew G. Knepley     if (!incall) {
475434b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4755648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
475606fc46c8SMatthew G. Knepley       if (flg) {
475706fc46c8SMatthew G. Knepley         PetscConvEst conv;
475846079b62SMatthew G. Knepley         DM           dm;
475946079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
476046079b62SMatthew G. Knepley         PetscInt     Nf;
476106fc46c8SMatthew G. Knepley 
476206fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
47639566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
47649566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
47659566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
47669566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
47679566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
47689566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
47699566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
47709566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
47719566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
47729566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
47739566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4774648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
47759566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
47769566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
477706fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
477806fc46c8SMatthew G. Knepley       }
477934b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4780b2588ea6SMatthew G. Knepley       num = 1;
47819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
478234b4d3a8SMatthew G. Knepley       if (flg) {
478334b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
478434b4d3a8SMatthew G. Knepley 
478534b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
47869566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
47879566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
47889566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
47899566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
47909566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
47919566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
47929566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
479334b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
479434b4d3a8SMatthew G. Knepley       }
47957c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
47967c88af5aSMatthew G. Knepley       num = 0;
47979566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
47987c88af5aSMatthew G. Knepley       if (num) {
47997c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
48007c88af5aSMatthew G. Knepley 
48017c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
48029566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
48039566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48049566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48069566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4807e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48089566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48099566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
48107c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
48117c88af5aSMatthew G. Knepley       }
481206fc46c8SMatthew G. Knepley     }
481306fc46c8SMatthew G. Knepley   }
4814ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4815caa4e7f2SJed Brown   if (!x) {
48169566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48179566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4818a69afd8bSBarry Smith     x = xcreated;
4819a69afd8bSBarry Smith   }
48209566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4821f05ece33SBarry Smith 
48229566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4823efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
482485385478SLisandro Dalcin     /* set solution vector */
48259566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48269566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
482785385478SLisandro Dalcin     snes->vec_sol = x;
48289566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4829caa4e7f2SJed Brown 
4830caa4e7f2SJed Brown     /* set affine vector if provided */
48319566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48329566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
483385385478SLisandro Dalcin     snes->vec_rhs = b;
483485385478SLisandro Dalcin 
48355f80ce2aSJacob 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");
48365f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4837dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4838aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48399566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48409566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48413f149594SLisandro Dalcin 
48427eee914bSBarry Smith     if (!grid) {
48439927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4844dd568438SSatish Balay     }
4845d25893d9SBarry Smith 
4846abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
48479371c9d4SSatish Balay     if (snes->counters_reset) {
48489371c9d4SSatish Balay       snes->nfuncs      = 0;
48499371c9d4SSatish Balay       snes->linear_its  = 0;
48509371c9d4SSatish Balay       snes->numFailures = 0;
48519371c9d4SSatish Balay     }
4852d5e45103SBarry Smith 
48532d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
48549566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4855dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
48569566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
48572d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4858422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
48593f149594SLisandro Dalcin 
486037ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
486137ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
486237ec4e1aSPeter Brune 
4863648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
48649566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4865c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
48669566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
48675968eb51SBarry Smith 
48685f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
48699c8e83a9SBarry Smith     if (snes->reason < 0) break;
4870efd51863SBarry Smith     if (grid < snes->gridsequence) {
4871efd51863SBarry Smith       DM  fine;
4872efd51863SBarry Smith       Vec xnew;
4873efd51863SBarry Smith       Mat interp;
4874efd51863SBarry Smith 
48759566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
48765f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
48779566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
48789566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
48799566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
48809566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
48819566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4882efd51863SBarry Smith       x = xnew;
4883efd51863SBarry Smith 
48849566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
48859566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
48869566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
48879566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
48889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4889efd51863SBarry Smith     }
4890efd51863SBarry Smith   }
48919566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
48929566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
48939566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
48949566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
48953f7e2da0SPeter Brune 
48969566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
48979566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
48983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48999b94acceSBarry Smith }
49009b94acceSBarry Smith 
49019b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
49029b94acceSBarry Smith 
4903cc4c1da9SBarry Smith /*@
49044b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
49059b94acceSBarry Smith 
4906c3339decSBarry Smith   Collective
4907fee21e36SBarry Smith 
4908c7afd0dbSLois Curfman McInnes   Input Parameters:
4909f6dfbefdSBarry Smith + snes - the `SNES` context
4910454a90a3SBarry Smith - type - a known method
4911c7afd0dbSLois Curfman McInnes 
4912c7afd0dbSLois Curfman McInnes   Options Database Key:
4913454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
491404d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4915ae12b187SLois Curfman McInnes 
4916dc4c0fb0SBarry Smith   Level: intermediate
4917dc4c0fb0SBarry Smith 
49189b94acceSBarry Smith   Notes:
4919e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4920f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4921c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49224a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4923c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49249b94acceSBarry Smith 
4925f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4926f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4927ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4928ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4929f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4930ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4931ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4932ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4933ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4934b0a32e0cSBarry Smith   appropriate method.
493536851e7fSLois Curfman McInnes 
4936420bcc1bSBarry Smith   Developer Note:
4937f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4938f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
49398f6c3df8SBarry Smith 
49401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49419b94acceSBarry Smith @*/
4942d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4943d71ae5a4SJacob Faibussowitsch {
4944ace3abfcSBarry Smith   PetscBool match;
49455f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
49463a40ed3dSBarry Smith 
49473a40ed3dSBarry Smith   PetscFunctionBegin;
49480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49494f572ea9SToby Isaac   PetscAssertPointer(type, 2);
495082bf6240SBarry Smith 
49519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
49523ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
495392ff6ae8SBarry Smith 
49549566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
49556adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
495675396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4957dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
495875396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
49599e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
49609e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
49619e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
49629e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
49639e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
49647fe760d5SStefano Zampini 
49657fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
49669566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
49677fe760d5SStefano Zampini 
496875396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
496975396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4970f5af7f23SKarl Rupp 
49719566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
49729566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
49733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49749b94acceSBarry Smith }
49759b94acceSBarry Smith 
4976cc4c1da9SBarry Smith /*@
4977f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
49789b94acceSBarry Smith 
4979c7afd0dbSLois Curfman McInnes   Not Collective
4980c7afd0dbSLois Curfman McInnes 
49819b94acceSBarry Smith   Input Parameter:
49824b0e389bSBarry Smith . snes - nonlinear solver context
49839b94acceSBarry Smith 
49849b94acceSBarry Smith   Output Parameter:
4985f6dfbefdSBarry Smith . type - `SNES` method (a character string)
49869b94acceSBarry Smith 
498736851e7fSLois Curfman McInnes   Level: intermediate
498836851e7fSLois Curfman McInnes 
49891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
49909b94acceSBarry Smith @*/
4991d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4992d71ae5a4SJacob Faibussowitsch {
49933a40ed3dSBarry Smith   PetscFunctionBegin;
49940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49954f572ea9SToby Isaac   PetscAssertPointer(type, 2);
49967adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
49973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49989b94acceSBarry Smith }
49999b94acceSBarry Smith 
50003cd8a7caSMatthew G. Knepley /*@
5001f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
50023cd8a7caSMatthew G. Knepley 
5003c3339decSBarry Smith   Logically Collective
50043cd8a7caSMatthew G. Knepley 
50053cd8a7caSMatthew G. Knepley   Input Parameters:
5006f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
50073cd8a7caSMatthew G. Knepley - u    - the solution vector
50083cd8a7caSMatthew G. Knepley 
50093cd8a7caSMatthew G. Knepley   Level: beginner
50103cd8a7caSMatthew G. Knepley 
50111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
50123cd8a7caSMatthew G. Knepley @*/
5013d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5014d71ae5a4SJacob Faibussowitsch {
50153cd8a7caSMatthew G. Knepley   DM dm;
50163cd8a7caSMatthew G. Knepley 
50173cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
50183cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50193cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
50219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
50223cd8a7caSMatthew G. Knepley 
50233cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
50243cd8a7caSMatthew G. Knepley 
50259566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50269566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
50273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50283cd8a7caSMatthew G. Knepley }
50293cd8a7caSMatthew G. Knepley 
503052baeb72SSatish Balay /*@
50319b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
5032f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50339b94acceSBarry Smith 
5034420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5035c7afd0dbSLois Curfman McInnes 
50369b94acceSBarry Smith   Input Parameter:
5037f6dfbefdSBarry Smith . snes - the `SNES` context
50389b94acceSBarry Smith 
50399b94acceSBarry Smith   Output Parameter:
50409b94acceSBarry Smith . x - the solution
50419b94acceSBarry Smith 
504270e92668SMatthew Knepley   Level: intermediate
504336851e7fSLois Curfman McInnes 
50441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
50459b94acceSBarry Smith @*/
5046d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5047d71ae5a4SJacob Faibussowitsch {
50483a40ed3dSBarry Smith   PetscFunctionBegin;
50490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50504f572ea9SToby Isaac   PetscAssertPointer(x, 2);
505185385478SLisandro Dalcin   *x = snes->vec_sol;
50523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
505370e92668SMatthew Knepley }
505470e92668SMatthew Knepley 
505552baeb72SSatish Balay /*@
50569b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
50579b94acceSBarry Smith   stored.
50589b94acceSBarry Smith 
5059420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5060c7afd0dbSLois Curfman McInnes 
50619b94acceSBarry Smith   Input Parameter:
5062f6dfbefdSBarry Smith . snes - the `SNES` context
50639b94acceSBarry Smith 
50649b94acceSBarry Smith   Output Parameter:
50659b94acceSBarry Smith . x - the solution update
50669b94acceSBarry Smith 
506736851e7fSLois Curfman McInnes   Level: advanced
506836851e7fSLois Curfman McInnes 
50691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
50709b94acceSBarry Smith @*/
5071d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5072d71ae5a4SJacob Faibussowitsch {
50733a40ed3dSBarry Smith   PetscFunctionBegin;
50740700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50754f572ea9SToby Isaac   PetscAssertPointer(x, 2);
507685385478SLisandro Dalcin   *x = snes->vec_sol_update;
50773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50789b94acceSBarry Smith }
50799b94acceSBarry Smith 
50809b94acceSBarry Smith /*@C
5081f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
50829b94acceSBarry Smith 
5083420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5084c7afd0dbSLois Curfman McInnes 
50859b94acceSBarry Smith   Input Parameter:
5086f6dfbefdSBarry Smith . snes - the `SNES` context
50879b94acceSBarry Smith 
5088d8d19677SJose E. Roman   Output Parameters:
5089dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
50908434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5091dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
50929b94acceSBarry Smith 
509336851e7fSLois Curfman McInnes   Level: advanced
509436851e7fSLois Curfman McInnes 
5095f6dfbefdSBarry Smith   Note:
5096dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
509704edfde5SBarry Smith 
50988434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
50999b94acceSBarry Smith @*/
51008434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5101d71ae5a4SJacob Faibussowitsch {
51026cab3a1bSJed Brown   DM dm;
5103a63bb30eSJed Brown 
51043a40ed3dSBarry Smith   PetscFunctionBegin;
51050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5106a63bb30eSJed Brown   if (r) {
5107a63bb30eSJed Brown     if (!snes->vec_func) {
5108a63bb30eSJed Brown       if (snes->vec_rhs) {
51099566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5110a63bb30eSJed Brown       } else if (snes->vec_sol) {
51119566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5112a63bb30eSJed Brown       } else if (snes->dm) {
51139566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5114a63bb30eSJed Brown       }
5115a63bb30eSJed Brown     }
5116a63bb30eSJed Brown     *r = snes->vec_func;
5117a63bb30eSJed Brown   }
51189566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51199566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
51203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51219b94acceSBarry Smith }
51229b94acceSBarry Smith 
5123c79ef259SPeter Brune /*@C
512437fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5125c79ef259SPeter Brune 
5126c79ef259SPeter Brune   Input Parameter:
5127f6dfbefdSBarry Smith . snes - the `SNES` context
5128c79ef259SPeter Brune 
5129d8d19677SJose E. Roman   Output Parameters:
51308434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5131dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5132c79ef259SPeter Brune 
5133c79ef259SPeter Brune   Level: advanced
5134c79ef259SPeter Brune 
51358434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5136c79ef259SPeter Brune @*/
51378434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5138d71ae5a4SJacob Faibussowitsch {
51396cab3a1bSJed Brown   DM dm;
51406cab3a1bSJed Brown 
5141646217ecSPeter Brune   PetscFunctionBegin;
5142646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51439566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51449566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
51453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5146646217ecSPeter Brune }
5147646217ecSPeter Brune 
5148cc4c1da9SBarry Smith /*@
51493c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5150f6dfbefdSBarry Smith   `SNES` options in the database.
51513c7409f5SSatish Balay 
5152c3339decSBarry Smith   Logically Collective
5153fee21e36SBarry Smith 
5154d8d19677SJose E. Roman   Input Parameters:
5155f6dfbefdSBarry Smith + snes   - the `SNES` context
5156c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5157c7afd0dbSLois Curfman McInnes 
5158dc4c0fb0SBarry Smith   Level: advanced
5159dc4c0fb0SBarry Smith 
5160f6dfbefdSBarry Smith   Note:
5161a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5162c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5163d850072dSLois Curfman McInnes 
51641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
51653c7409f5SSatish Balay @*/
5166d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5167d71ae5a4SJacob Faibussowitsch {
51683a40ed3dSBarry Smith   PetscFunctionBegin;
51690700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51709566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
51719566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
517235f5d045SPeter Brune   if (snes->linesearch) {
51739566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51749566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
517535f5d045SPeter Brune   }
51769566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
51773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51783c7409f5SSatish Balay }
51793c7409f5SSatish Balay 
5180cc4c1da9SBarry Smith /*@
5181f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5182f6dfbefdSBarry Smith   `SNES` options in the database.
51833c7409f5SSatish Balay 
5184c3339decSBarry Smith   Logically Collective
5185fee21e36SBarry Smith 
5186c7afd0dbSLois Curfman McInnes   Input Parameters:
5187f6dfbefdSBarry Smith + snes   - the `SNES` context
5188c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5189c7afd0dbSLois Curfman McInnes 
5190dc4c0fb0SBarry Smith   Level: advanced
5191dc4c0fb0SBarry Smith 
5192f6dfbefdSBarry Smith   Note:
5193a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5194c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5195d850072dSLois Curfman McInnes 
51961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
51973c7409f5SSatish Balay @*/
5198d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5199d71ae5a4SJacob Faibussowitsch {
52003a40ed3dSBarry Smith   PetscFunctionBegin;
52010700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52029566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
52039566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
520435f5d045SPeter Brune   if (snes->linesearch) {
52059566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
52069566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
520735f5d045SPeter Brune   }
52089566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
52093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52103c7409f5SSatish Balay }
52113c7409f5SSatish Balay 
5212cc4c1da9SBarry Smith /*@
5213f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5214f6dfbefdSBarry Smith   `SNES` options in the database.
52153c7409f5SSatish Balay 
5216c7afd0dbSLois Curfman McInnes   Not Collective
5217c7afd0dbSLois Curfman McInnes 
52183c7409f5SSatish Balay   Input Parameter:
5219f6dfbefdSBarry Smith . snes - the `SNES` context
52203c7409f5SSatish Balay 
52213c7409f5SSatish Balay   Output Parameter:
52223c7409f5SSatish Balay . prefix - pointer to the prefix string used
52233c7409f5SSatish Balay 
522436851e7fSLois Curfman McInnes   Level: advanced
522536851e7fSLois Curfman McInnes 
5226420bcc1bSBarry Smith   Fortran Note:
5227dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5228dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5229dc4c0fb0SBarry Smith 
52301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52313c7409f5SSatish Balay @*/
5232d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5233d71ae5a4SJacob Faibussowitsch {
52343a40ed3dSBarry Smith   PetscFunctionBegin;
52350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52369566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52383c7409f5SSatish Balay }
52393c7409f5SSatish Balay 
52403cea93caSBarry Smith /*@C
52411c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
52421c84c290SBarry Smith 
524320f4b53cSBarry Smith   Not Collective
52441c84c290SBarry Smith 
52451c84c290SBarry Smith   Input Parameters:
524620f4b53cSBarry Smith + sname    - name of a new user-defined solver
524720f4b53cSBarry Smith - function - routine to create method context
52481c84c290SBarry Smith 
5249dc4c0fb0SBarry Smith   Level: advanced
5250dc4c0fb0SBarry Smith 
5251f6dfbefdSBarry Smith   Note:
5252f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
52531c84c290SBarry Smith 
5254e4094ef1SJacob Faibussowitsch   Example Usage:
52551c84c290SBarry Smith .vb
5256bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
52571c84c290SBarry Smith .ve
52581c84c290SBarry Smith 
52591c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
52601c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
52611c84c290SBarry Smith   or at runtime via the option
52621c84c290SBarry Smith $     -snes_type my_solver
52631c84c290SBarry Smith 
52641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
52653cea93caSBarry Smith @*/
5266d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5267d71ae5a4SJacob Faibussowitsch {
5268b2002411SLois Curfman McInnes   PetscFunctionBegin;
52699566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
52709566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
52713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5272b2002411SLois Curfman McInnes }
5273da9b6338SBarry Smith 
5274d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5275d71ae5a4SJacob Faibussowitsch {
527677431f27SBarry Smith   PetscInt    N, i, j;
5277da9b6338SBarry Smith   Vec         u, uh, fh;
5278da9b6338SBarry Smith   PetscScalar value;
5279da9b6338SBarry Smith   PetscReal   norm;
5280da9b6338SBarry Smith 
5281da9b6338SBarry Smith   PetscFunctionBegin;
52829566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
52839566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
52849566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5285da9b6338SBarry Smith 
5286da9b6338SBarry Smith   /* currently only works for sequential */
52879566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
52889566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5289da9b6338SBarry Smith   for (i = 0; i < N; i++) {
52909566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
529163a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5292da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
52938b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
52949566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
52959566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
52969566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
529763a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5298da9b6338SBarry Smith       value = -value;
52999566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5300da9b6338SBarry Smith     }
5301da9b6338SBarry Smith   }
53029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
53039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
53043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5305da9b6338SBarry Smith }
530671f87433Sdalcinl 
530771f87433Sdalcinl /*@
5308f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
530971f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
531071f87433Sdalcinl   Newton method.
531171f87433Sdalcinl 
5312c3339decSBarry Smith   Logically Collective
531371f87433Sdalcinl 
531471f87433Sdalcinl   Input Parameters:
5315f6dfbefdSBarry Smith + snes - `SNES` context
5316f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
531771f87433Sdalcinl 
5318f6dfbefdSBarry Smith   Options Database Keys:
531964ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
532064ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
532164ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
532264ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
532364ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
532464ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
532564ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
532664ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
532764ba62caSBarry Smith 
5328dc4c0fb0SBarry Smith   Level: advanced
5329dc4c0fb0SBarry Smith 
5330f6dfbefdSBarry Smith   Note:
5331f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
533271f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
53331d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
533471f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
533571f87433Sdalcinl   solver.
533671f87433Sdalcinl 
53371cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
533871f87433Sdalcinl @*/
5339d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5340d71ae5a4SJacob Faibussowitsch {
534171f87433Sdalcinl   PetscFunctionBegin;
53420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5343acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
534471f87433Sdalcinl   snes->ksp_ewconv = flag;
53453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
534671f87433Sdalcinl }
534771f87433Sdalcinl 
534871f87433Sdalcinl /*@
5349f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
535071f87433Sdalcinl   for computing relative tolerance for linear solvers within an
535171f87433Sdalcinl   inexact Newton method.
535271f87433Sdalcinl 
535371f87433Sdalcinl   Not Collective
535471f87433Sdalcinl 
535571f87433Sdalcinl   Input Parameter:
5356f6dfbefdSBarry Smith . snes - `SNES` context
535771f87433Sdalcinl 
535871f87433Sdalcinl   Output Parameter:
5359f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
536071f87433Sdalcinl 
536171f87433Sdalcinl   Level: advanced
536271f87433Sdalcinl 
53631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
536471f87433Sdalcinl @*/
5365d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5366d71ae5a4SJacob Faibussowitsch {
536771f87433Sdalcinl   PetscFunctionBegin;
53680700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
53694f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
537071f87433Sdalcinl   *flag = snes->ksp_ewconv;
53713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
537271f87433Sdalcinl }
537371f87433Sdalcinl 
537471f87433Sdalcinl /*@
5375fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
537671f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
537771f87433Sdalcinl   Newton method.
537871f87433Sdalcinl 
5379c3339decSBarry Smith   Logically Collective
538071f87433Sdalcinl 
538171f87433Sdalcinl   Input Parameters:
5382f6dfbefdSBarry Smith + snes      - `SNES` context
53830f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
538471f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
538571f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
538671f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
538771f87433Sdalcinl              (0 <= gamma2 <= 1)
538871f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
538971f87433Sdalcinl . alpha2    - power for safeguard
539071f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
539171f87433Sdalcinl 
5392dc4c0fb0SBarry Smith   Level: advanced
5393dc4c0fb0SBarry Smith 
5394f6dfbefdSBarry Smith   Notes:
539571f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
539671f87433Sdalcinl 
5397*77e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
539871f87433Sdalcinl 
53991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
540071f87433Sdalcinl @*/
5401d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5402d71ae5a4SJacob Faibussowitsch {
5403fa9f3622SBarry Smith   SNESKSPEW *kctx;
54045fd66863SKarl Rupp 
540571f87433Sdalcinl   PetscFunctionBegin;
54060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5407fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54085f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5409c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5410c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5411c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5412c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5413c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5414c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5415c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
541671f87433Sdalcinl 
5417*77e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
5418*77e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
5419*77e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
5420*77e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
5421*77e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
5422*77e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
5423*77e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
542471f87433Sdalcinl 
54250f0abf79SStefano 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);
54260b121fc5SBarry 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);
54270b121fc5SBarry 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);
54280b121fc5SBarry 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);
54290b121fc5SBarry 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);
54300b121fc5SBarry 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);
54313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
543271f87433Sdalcinl }
543371f87433Sdalcinl 
543471f87433Sdalcinl /*@
5435fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
543671f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
543771f87433Sdalcinl   Newton method.
543871f87433Sdalcinl 
543971f87433Sdalcinl   Not Collective
544071f87433Sdalcinl 
544197bb3fdcSJose E. Roman   Input Parameter:
5442f6dfbefdSBarry Smith . snes - `SNES` context
544371f87433Sdalcinl 
544471f87433Sdalcinl   Output Parameters:
54450f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
544671f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
544771f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5448bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
544971f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
545071f87433Sdalcinl . alpha2    - power for safeguard
545171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
545271f87433Sdalcinl 
545371f87433Sdalcinl   Level: advanced
545471f87433Sdalcinl 
54551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
545671f87433Sdalcinl @*/
5457d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5458d71ae5a4SJacob Faibussowitsch {
5459fa9f3622SBarry Smith   SNESKSPEW *kctx;
54605fd66863SKarl Rupp 
546171f87433Sdalcinl   PetscFunctionBegin;
54620700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5463fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54645f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
546571f87433Sdalcinl   if (version) *version = kctx->version;
546671f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
546771f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
546871f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
546971f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
547071f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
547171f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
54723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
547371f87433Sdalcinl }
547471f87433Sdalcinl 
54755c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5476d71ae5a4SJacob Faibussowitsch {
54775c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5478fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
5479*77e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
548071f87433Sdalcinl 
548171f87433Sdalcinl   PetscFunctionBegin;
54823ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
548330058271SDmitry Karpeev   if (!snes->iter) {
548430058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
54859566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
54860f0abf79SStefano Zampini   } else {
54870fdf79fbSJacob 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);
548871f87433Sdalcinl     if (kctx->version == 1) {
54890f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
549085ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
549171f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
549271f87433Sdalcinl     } else if (kctx->version == 2) {
549385ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
549485ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
549571f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
549671f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
549785ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
549871f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
549985ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
550071f87433Sdalcinl       stol = PetscMax(rtol, stol);
550171f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
550271f87433Sdalcinl       /* safeguard: avoid oversolving */
550330058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
550471f87433Sdalcinl       stol = PetscMax(rtol, stol);
550571f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
55060fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
55070fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
55080f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
55090f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
55100f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
55110f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
55120f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
55130f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
55140f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
55150f0abf79SStefano Zampini 
5516a4598233SStefano 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;
55170f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
55180f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
55190f0abf79SStefano Zampini       kctx->rk_last     = rk;
55200fdf79fbSJacob Faibussowitsch     }
55210f0abf79SStefano Zampini   }
55220f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
552371f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
5524*77e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
552563a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
55263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
552771f87433Sdalcinl }
552871f87433Sdalcinl 
55295c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5530d71ae5a4SJacob Faibussowitsch {
55315c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5532fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
553371f87433Sdalcinl   PCSide     pcside;
553471f87433Sdalcinl   Vec        lres;
553571f87433Sdalcinl 
553671f87433Sdalcinl   PetscFunctionBegin;
55373ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
55389566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
553971dbe336SPeter Brune   kctx->norm_last = snes->norm;
55400f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
55414f00ce20SMatthew G. Knepley     PC        pc;
55420f0abf79SStefano Zampini     PetscBool getRes;
55434f00ce20SMatthew G. Knepley 
55449566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
55450f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
55460f0abf79SStefano Zampini     if (!getRes) {
55470f0abf79SStefano Zampini       KSPNormType normtype;
55480f0abf79SStefano Zampini 
55490f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
55500f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
55510f0abf79SStefano Zampini     }
55529566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
55530f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
55549566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
555571f87433Sdalcinl     } else {
555671f87433Sdalcinl       /* KSP residual is preconditioned residual */
555771f87433Sdalcinl       /* compute true linear residual norm */
55580f0abf79SStefano Zampini       Mat J;
55590f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
55609566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
55610f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
55629566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
55639566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
55649566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
556571f87433Sdalcinl     }
556671f87433Sdalcinl   }
55673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
556871f87433Sdalcinl }
556971f87433Sdalcinl 
5570d4211eb9SBarry Smith /*@
5571f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5572d4211eb9SBarry Smith 
5573420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5574d4211eb9SBarry Smith 
5575d4211eb9SBarry Smith   Input Parameter:
5576f6dfbefdSBarry Smith . snes - the `SNES` context
5577d4211eb9SBarry Smith 
5578d4211eb9SBarry Smith   Output Parameter:
5579f6dfbefdSBarry Smith . ksp - the `KSP` context
5580d4211eb9SBarry Smith 
5581dc4c0fb0SBarry Smith   Level: beginner
5582dc4c0fb0SBarry Smith 
5583d4211eb9SBarry Smith   Notes:
5584f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5585d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5586f6dfbefdSBarry Smith   `PC` contexts as well.
5587f6dfbefdSBarry Smith 
5588f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5589d4211eb9SBarry Smith 
55901cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5591d4211eb9SBarry Smith @*/
5592d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5593d71ae5a4SJacob Faibussowitsch {
559471f87433Sdalcinl   PetscFunctionBegin;
5595d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55964f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5597d4211eb9SBarry Smith 
5598d4211eb9SBarry Smith   if (!snes->ksp) {
55999566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
56009566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5601d4211eb9SBarry Smith 
56025c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
56035c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5604a5c2985bSBarry Smith 
56059566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
56069566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5607d4211eb9SBarry Smith   }
5608d4211eb9SBarry Smith   *ksp = snes->ksp;
56093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
561071f87433Sdalcinl }
56116c699258SBarry Smith 
5612af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
56136c699258SBarry Smith /*@
5614f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
56156c699258SBarry Smith 
5616c3339decSBarry Smith   Logically Collective
56176c699258SBarry Smith 
56186c699258SBarry Smith   Input Parameters:
56192a808120SBarry Smith + snes - the nonlinear solver context
5620420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5621dc4c0fb0SBarry Smith 
5622dc4c0fb0SBarry Smith   Level: intermediate
56236c699258SBarry Smith 
5624f6dfbefdSBarry Smith   Note:
5625f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5626f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5627e03a659cSJed Brown   problems using the same function space.
5628e03a659cSJed Brown 
5629420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
56306c699258SBarry Smith @*/
5631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5632d71ae5a4SJacob Faibussowitsch {
5633345fed2cSBarry Smith   KSP    ksp;
5634942e3340SBarry Smith   DMSNES sdm;
56356c699258SBarry Smith 
56366c699258SBarry Smith   PetscFunctionBegin;
56370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56382a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
56399566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5640942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
564151f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
56429566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
56439566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5644f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
56456cab3a1bSJed Brown     }
56469566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
56479566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
56486cab3a1bSJed Brown   }
56496c699258SBarry Smith   snes->dm     = dm;
5650116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5651f5af7f23SKarl Rupp 
56529566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
56539566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
56549566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5655efd4aadfSBarry Smith   if (snes->npc) {
56569566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
56579566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
56582c155ee1SBarry Smith   }
56593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56606c699258SBarry Smith }
56616c699258SBarry Smith 
56626c699258SBarry Smith /*@
5663420bcc1bSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners
56646c699258SBarry Smith 
5665f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
56666c699258SBarry Smith 
56676c699258SBarry Smith   Input Parameter:
5668420bcc1bSBarry Smith . snes - the `SNES` context
56696c699258SBarry Smith 
56706c699258SBarry Smith   Output Parameter:
5671420bcc1bSBarry Smith . dm - the `DM`
56726c699258SBarry Smith 
56736c699258SBarry Smith   Level: intermediate
56746c699258SBarry Smith 
5675420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
56766c699258SBarry Smith @*/
5677d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5678d71ae5a4SJacob Faibussowitsch {
56796c699258SBarry Smith   PetscFunctionBegin;
56800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56816cab3a1bSJed Brown   if (!snes->dm) {
56829566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5683116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
56846cab3a1bSJed Brown   }
56856c699258SBarry Smith   *dm = snes->dm;
56863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56876c699258SBarry Smith }
56880807856dSBarry Smith 
568931823bd8SMatthew G Knepley /*@
5690be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
569131823bd8SMatthew G Knepley 
5692c3339decSBarry Smith   Collective
569331823bd8SMatthew G Knepley 
569431823bd8SMatthew G Knepley   Input Parameters:
5695f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5696420bcc1bSBarry Smith - npc  - the nonlinear preconditioner object
569731823bd8SMatthew G Knepley 
5698dc4c0fb0SBarry Smith   Level: developer
5699dc4c0fb0SBarry Smith 
570031823bd8SMatthew G Knepley   Notes:
5701f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
570231823bd8SMatthew G Knepley   to configure it using the API).
570331823bd8SMatthew G Knepley 
5704f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5705f6dfbefdSBarry Smith 
5706420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
570731823bd8SMatthew G Knepley @*/
5708d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5709d71ae5a4SJacob Faibussowitsch {
571031823bd8SMatthew G Knepley   PetscFunctionBegin;
571131823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5712f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5713f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5714f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
57159566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5716f6dfbefdSBarry Smith   snes->npc = npc;
57173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
571831823bd8SMatthew G Knepley }
571931823bd8SMatthew G Knepley 
572031823bd8SMatthew G Knepley /*@
5721f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
572231823bd8SMatthew G Knepley 
5723f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
572431823bd8SMatthew G Knepley 
572531823bd8SMatthew G Knepley   Input Parameter:
5726f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
572731823bd8SMatthew G Knepley 
572831823bd8SMatthew G Knepley   Output Parameter:
5729e4094ef1SJacob Faibussowitsch . pc - preconditioner context
573031823bd8SMatthew G Knepley 
5731f6dfbefdSBarry Smith   Options Database Key:
5732f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5733b5badacbSBarry Smith 
5734dc4c0fb0SBarry Smith   Level: developer
5735dc4c0fb0SBarry Smith 
573695452b02SPatrick Sanan   Notes:
5737f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5738be95d8f1SBarry Smith 
5739f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5740f6dfbefdSBarry Smith   `SNES`
5741951fe5abSBarry Smith 
57421cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
574331823bd8SMatthew G Knepley @*/
5744d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5745d71ae5a4SJacob Faibussowitsch {
5746a64e098fSPeter Brune   const char *optionsprefix;
574731823bd8SMatthew G Knepley 
574831823bd8SMatthew G Knepley   PetscFunctionBegin;
574931823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57504f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5751efd4aadfSBarry Smith   if (!snes->npc) {
5752ec785e5bSStefano Zampini     void *ctx;
5753ec785e5bSStefano Zampini 
57549566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
57559566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
57569566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57579566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
57589566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5759fb87a551SStefano Zampini     if (snes->ops->usercompute) {
5760fb87a551SStefano Zampini       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy));
5761fb87a551SStefano Zampini     } else {
5762ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5763ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5764fb87a551SStefano Zampini     }
57659566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
576631823bd8SMatthew G Knepley   }
5767efd4aadfSBarry Smith   *pc = snes->npc;
57683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
576931823bd8SMatthew G Knepley }
577031823bd8SMatthew G Knepley 
57713ad1a0b9SPatrick Farrell /*@
57723ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
57733ad1a0b9SPatrick Farrell 
57743ad1a0b9SPatrick Farrell   Not Collective
57753ad1a0b9SPatrick Farrell 
57763ad1a0b9SPatrick Farrell   Input Parameter:
5777f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57783ad1a0b9SPatrick Farrell 
57793ad1a0b9SPatrick Farrell   Output Parameter:
5780420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
57813ad1a0b9SPatrick Farrell 
57823ad1a0b9SPatrick Farrell   Level: developer
57833ad1a0b9SPatrick Farrell 
57841cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
57853ad1a0b9SPatrick Farrell @*/
5786d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5787d71ae5a4SJacob Faibussowitsch {
57883ad1a0b9SPatrick Farrell   PetscFunctionBegin;
57893ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5790efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
57913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57923ad1a0b9SPatrick Farrell }
57933ad1a0b9SPatrick Farrell 
5794c40d0f55SPeter Brune /*@
5795420bcc1bSBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side.
5796c40d0f55SPeter Brune 
5797c3339decSBarry Smith   Logically Collective
5798c40d0f55SPeter Brune 
5799c40d0f55SPeter Brune   Input Parameter:
5800f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5801c40d0f55SPeter Brune 
5802c40d0f55SPeter Brune   Output Parameter:
5803c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5804c40d0f55SPeter Brune .vb
58052d547940SBarry Smith       PC_LEFT - left preconditioning
58062d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5807c40d0f55SPeter Brune .ve
5808c40d0f55SPeter Brune 
5809f6dfbefdSBarry Smith   Options Database Key:
581067b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5811c40d0f55SPeter Brune 
5812dc4c0fb0SBarry Smith   Level: intermediate
5813dc4c0fb0SBarry Smith 
5814f6dfbefdSBarry Smith   Note:
5815f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
58162d547940SBarry Smith 
5817420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5818c40d0f55SPeter Brune @*/
5819d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5820d71ae5a4SJacob Faibussowitsch {
5821c40d0f55SPeter Brune   PetscFunctionBegin;
5822c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5823c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5824b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
582554c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5826efd4aadfSBarry Smith   snes->npcside = side;
58273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5828c40d0f55SPeter Brune }
5829c40d0f55SPeter Brune 
5830c40d0f55SPeter Brune /*@
5831be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5832c40d0f55SPeter Brune 
5833c40d0f55SPeter Brune   Not Collective
5834c40d0f55SPeter Brune 
5835c40d0f55SPeter Brune   Input Parameter:
5836f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5837c40d0f55SPeter Brune 
5838c40d0f55SPeter Brune   Output Parameter:
5839c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5840c40d0f55SPeter Brune .vb
5841f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5842f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5843c40d0f55SPeter Brune .ve
5844c40d0f55SPeter Brune 
5845c40d0f55SPeter Brune   Level: intermediate
5846c40d0f55SPeter Brune 
5847420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5848c40d0f55SPeter Brune @*/
5849d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5850d71ae5a4SJacob Faibussowitsch {
5851c40d0f55SPeter Brune   PetscFunctionBegin;
5852c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58534f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5854efd4aadfSBarry Smith   *side = snes->npcside;
58553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5856c40d0f55SPeter Brune }
5857c40d0f55SPeter Brune 
58589e764e56SPeter Brune /*@
5859420bcc1bSBarry Smith   SNESSetLineSearch - Sets the linesearch to be used for `SNES`
58609e764e56SPeter Brune 
5861c3339decSBarry Smith   Collective
58629e764e56SPeter Brune 
58639e764e56SPeter Brune   Input Parameters:
5864f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
58659e764e56SPeter Brune - linesearch - the linesearch object
58669e764e56SPeter Brune 
5867dc4c0fb0SBarry Smith   Level: developer
5868dc4c0fb0SBarry Smith 
5869f6dfbefdSBarry Smith   Note:
5870420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
58719e764e56SPeter Brune   to configure it using the API).
58729e764e56SPeter Brune 
5873420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
58749e764e56SPeter Brune @*/
5875d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5876d71ae5a4SJacob Faibussowitsch {
58779e764e56SPeter Brune   PetscFunctionBegin;
58789e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5879f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
58809e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
58819566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
58829566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5883f5af7f23SKarl Rupp 
58849e764e56SPeter Brune   snes->linesearch = linesearch;
58853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58869e764e56SPeter Brune }
58879e764e56SPeter Brune 
5888a34ceb2aSJed Brown /*@
5889420bcc1bSBarry Smith   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5890f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
58919e764e56SPeter Brune 
58929e764e56SPeter Brune   Not Collective
58939e764e56SPeter Brune 
58949e764e56SPeter Brune   Input Parameter:
5895f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58969e764e56SPeter Brune 
58979e764e56SPeter Brune   Output Parameter:
58989e764e56SPeter Brune . linesearch - linesearch context
58999e764e56SPeter Brune 
5900162e0bf5SPeter Brune   Level: beginner
59019e764e56SPeter Brune 
59021cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
59039e764e56SPeter Brune @*/
5904d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5905d71ae5a4SJacob Faibussowitsch {
59069e764e56SPeter Brune   const char *optionsprefix;
59079e764e56SPeter Brune 
59089e764e56SPeter Brune   PetscFunctionBegin;
59099e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59104f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
59119e764e56SPeter Brune   if (!snes->linesearch) {
59129566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
59139566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
59149566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
59159566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
59169566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
59179e764e56SPeter Brune   }
59189e764e56SPeter Brune   *linesearch = snes->linesearch;
59193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59209e764e56SPeter Brune }
5921