xref: /petsc/src/snes/interface/snes.c (revision ceaaa4989964adb3f5eb130cb04b8f49c83e49c9)
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 
831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `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 
1061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `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 
1351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunction`, `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 
1651cc06b55SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `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
179f6dfbefdSBarry Smith   each Jacobian evaluation. By default, we check Jacobian domain error in the debug mode, and do 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 
1921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `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 /*@
2038383d7d7SFande Kong   SNESGetCheckJacobianDomainError - Get an indicator whether or not we are 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:
211f6dfbefdSBarry Smith . flg - `PETSC_FALSE` indicates that we don't check Jacobian domain errors after each Jacobian evaluation
2128383d7d7SFande Kong 
2138383d7d7SFande Kong   Level: advanced
2148383d7d7SFande Kong 
2151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `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 /*@
227f6dfbefdSBarry 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 /*@
251f6dfbefdSBarry Smith   SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()`;
25207b62357SFande Kong 
253c3339decSBarry Smith   Logically Collective
25407b62357SFande Kong 
2552fe279fdSBarry Smith   Input Parameter:
256f6dfbefdSBarry Smith . snes - the `SNES` context
25707b62357SFande Kong 
2582fe279fdSBarry Smith   Output Parameter:
259f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise.
26007b62357SFande Kong 
26107b62357SFande Kong   Level: advanced
26207b62357SFande Kong 
2631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()`
26407b62357SFande Kong @*/
265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror)
266d71ae5a4SJacob Faibussowitsch {
26707b62357SFande Kong   PetscFunctionBegin;
26807b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2694f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
27007b62357SFande Kong   *domainerror = snes->jacobiandomainerror;
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27207b62357SFande Kong }
27307b62357SFande Kong 
27455849f57SBarry Smith /*@C
275f6dfbefdSBarry Smith   SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
27655849f57SBarry Smith 
277c3339decSBarry Smith   Collective
27855849f57SBarry Smith 
27955849f57SBarry Smith   Input Parameters:
280e4094ef1SJacob Faibussowitsch + snes   - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
281f6dfbefdSBarry Smith            some related function before a call to `SNESLoad()`.
282f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
28355849f57SBarry Smith 
28455849f57SBarry Smith   Level: intermediate
28555849f57SBarry Smith 
286f6dfbefdSBarry Smith   Note:
287f6dfbefdSBarry Smith   The type is determined by the data in the file, any type set into the `SNES` before this call is ignored.
28855849f57SBarry Smith 
2891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
29055849f57SBarry Smith @*/
291d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
292d71ae5a4SJacob Faibussowitsch {
29355849f57SBarry Smith   PetscBool isbinary;
294060da220SMatthew G. Knepley   PetscInt  classid;
29555849f57SBarry Smith   char      type[256];
29655849f57SBarry Smith   KSP       ksp;
2972d53ad75SBarry Smith   DM        dm;
2982d53ad75SBarry Smith   DMSNES    dmsnes;
29955849f57SBarry Smith 
30055849f57SBarry Smith   PetscFunctionBegin;
3012d53ad75SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
30255849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3045f80ce2aSJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
30555849f57SBarry Smith 
3069566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
3075f80ce2aSJacob Faibussowitsch   PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3089566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3099566063dSJacob Faibussowitsch   PetscCall(SNESSetType(snes, type));
310dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, load, viewer);
3119566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3129566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &dmsnes));
3139566063dSJacob Faibussowitsch   PetscCall(DMSNESLoad(dmsnes, viewer));
3149566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
3159566063dSJacob Faibussowitsch   PetscCall(KSPLoad(ksp, viewer));
3163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31755849f57SBarry Smith }
3186a388c36SPeter Brune 
3199804daf3SBarry Smith #include <petscdraw.h>
320e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
321e04113cfSBarry Smith   #include <petscviewersaws.h>
322bfb97211SBarry Smith #endif
3238404b7f3SBarry Smith 
324fe2efc57SMark /*@C
325dc4c0fb0SBarry Smith   SNESViewFromOptions - View a `SNES` based on values in the options database
326fe2efc57SMark 
327c3339decSBarry Smith   Collective
328fe2efc57SMark 
329fe2efc57SMark   Input Parameters:
330f6dfbefdSBarry Smith + A    - the `SNES` context
331dc4c0fb0SBarry Smith . obj  - Optional object that provides the options prefix for the checks
332736c3998SJose E. Roman - name - command line option
333fe2efc57SMark 
334fe2efc57SMark   Level: intermediate
335f6dfbefdSBarry Smith 
3361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
337fe2efc57SMark @*/
338d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
339d71ae5a4SJacob Faibussowitsch {
340fe2efc57SMark   PetscFunctionBegin;
341fe2efc57SMark   PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
344fe2efc57SMark }
345fe2efc57SMark 
346789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
347789d8953SBarry Smith 
3487e2c5f70SBarry Smith /*@C
349dc4c0fb0SBarry Smith   SNESView - Prints or visualizes the `SNES` data structure.
3509b94acceSBarry Smith 
351c3339decSBarry Smith   Collective
352fee21e36SBarry Smith 
353c7afd0dbSLois Curfman McInnes   Input Parameters:
354f6dfbefdSBarry Smith + snes   - the `SNES` context
355f6dfbefdSBarry Smith - viewer - the `PetscViewer`
356c7afd0dbSLois Curfman McInnes 
3579b94acceSBarry Smith   Options Database Key:
358f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3599b94acceSBarry Smith 
360dc4c0fb0SBarry Smith   Level: beginner
361dc4c0fb0SBarry Smith 
3629b94acceSBarry Smith   Notes:
3639b94acceSBarry Smith   The available visualization contexts include
364f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
365f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
366c8a8ba5cSLois Curfman McInnes   output where only the first processor opens
367c8a8ba5cSLois Curfman McInnes   the file.  All other processors send their
368c8a8ba5cSLois Curfman McInnes   data to the first processor to print.
3699b94acceSBarry Smith 
370052bf0daSPierre Jolivet   The available formats include
371f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
372f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
373052bf0daSPierre Jolivet 
3743e081fefSLois Curfman McInnes   The user can open an alternative visualization context with
375f6dfbefdSBarry Smith   `PetscViewerASCIIOpen()` - output to a specified file.
3769b94acceSBarry Smith 
377f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
378595c91d4SBarry Smith 
3791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3809b94acceSBarry Smith @*/
381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
382d71ae5a4SJacob Faibussowitsch {
383fa9f3622SBarry Smith   SNESKSPEW     *kctx;
38494b7f48cSBarry Smith   KSP            ksp;
3857f1410a3SPeter Brune   SNESLineSearch linesearch;
38672a02f06SBarry Smith   PetscBool      iascii, isstring, isbinary, isdraw;
3872d53ad75SBarry Smith   DMSNES         dmsnes;
388e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
389536b137fSBarry Smith   PetscBool issaws;
390bfb97211SBarry Smith #endif
3919b94acceSBarry Smith 
3923a40ed3dSBarry Smith   PetscFunctionBegin;
3930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39448a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
3950700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
396c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, viewer, 2);
39774679c65SBarry Smith 
3989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
4009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
402e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
4039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
404bfb97211SBarry Smith #endif
40532077d6dSBarry Smith   if (iascii) {
406dc0571f2SMatthew G. Knepley     SNESNormSchedule normschedule;
4078404b7f3SBarry Smith     DM               dm;
4088404b7f3SBarry Smith     PetscErrorCode (*cJ)(SNES, Vec, Mat, Mat, void *);
4098404b7f3SBarry Smith     void       *ctx;
410789d8953SBarry Smith     const char *pre = "";
411dc0571f2SMatthew G. Knepley 
4129566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
41348a46eb9SPierre Jolivet     if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  SNES has not been set up so information may be incomplete\n"));
414e7788613SBarry Smith     if (snes->ops->view) {
4159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
416dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, view, viewer);
4179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
4180ef38995SBarry Smith     }
41963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
4209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42148a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4239566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4249566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
42548a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4269b94acceSBarry Smith     if (snes->ksp_ewconv) {
427fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4289b94acceSBarry Smith       if (kctx) {
42963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4329b94acceSBarry Smith       }
4339b94acceSBarry Smith     }
434eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
436eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
43763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
438eb1f6c34SBarry Smith     }
439eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
441eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
44263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
443eb1f6c34SBarry Smith     }
4449566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4459566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
446789d8953SBarry Smith     if (snes->mf_operator) {
4479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
448789d8953SBarry Smith       pre = "Preconditioning ";
449789d8953SBarry Smith     }
4508404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4528404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
454789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
455789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
456789d8953SBarry Smith       MatFDColoring fdcoloring;
4579566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
458789d8953SBarry Smith       if (fdcoloring) {
4599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
460789d8953SBarry Smith       } else {
4619566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
462789d8953SBarry Smith       }
463996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4658404b7f3SBarry Smith     }
4660f5bd95cSBarry Smith   } else if (isstring) {
467317d6ea6SBarry Smith     const char *type;
4689566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4699566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
470dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47155849f57SBarry Smith   } else if (isbinary) {
47255849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
47355849f57SBarry Smith     MPI_Comm    comm;
47455849f57SBarry Smith     PetscMPIInt rank;
47555849f57SBarry Smith     char        type[256];
47655849f57SBarry Smith 
4779566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
479dd400576SPatrick Sanan     if (rank == 0) {
4809566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4819566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4829566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48355849f57SBarry Smith     }
484dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
48572a02f06SBarry Smith   } else if (isdraw) {
48672a02f06SBarry Smith     PetscDraw draw;
48772a02f06SBarry Smith     char      str[36];
48889fd9fafSBarry Smith     PetscReal x, y, bottom, h;
48972a02f06SBarry Smith 
4909566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4919566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4929566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4939566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
4949566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
49589fd9fafSBarry Smith     bottom = y - h;
4969566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
497dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
498e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
499536b137fSBarry Smith   } else if (issaws) {
500d45a07a7SBarry Smith     PetscMPIInt rank;
5012657e9d9SBarry Smith     const char *name;
502d45a07a7SBarry Smith 
5039566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
505dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
506d45a07a7SBarry Smith       char dir[1024];
507d45a07a7SBarry Smith 
5089566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5099566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
510792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51148a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5129566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
513792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
514f05ece33SBarry Smith     }
515bfb97211SBarry Smith #endif
51672a02f06SBarry Smith   }
51772a02f06SBarry Smith   if (snes->linesearch) {
5189566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5209566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
52219bcc07fSBarry Smith   }
523efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5259566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5274a0c5b0cSMatthew G Knepley   }
5289566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5299566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5309566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5319566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5322c155ee1SBarry Smith   if (snes->usesksp) {
5339566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5359566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5372c155ee1SBarry Smith   }
53872a02f06SBarry Smith   if (isdraw) {
53972a02f06SBarry Smith     PetscDraw draw;
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5419566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5427f1410a3SPeter Brune   }
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5449b94acceSBarry Smith }
5459b94acceSBarry Smith 
54676b2cf59SMatthew Knepley /*
54776b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
54876b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
54976b2cf59SMatthew Knepley */
55076b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
551a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5526849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55376b2cf59SMatthew Knepley 
554ac226902SBarry Smith /*@C
555f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
55676b2cf59SMatthew Knepley 
55776b2cf59SMatthew Knepley   Not Collective
55876b2cf59SMatthew Knepley 
55976b2cf59SMatthew Knepley   Input Parameter:
56076b2cf59SMatthew Knepley . snescheck - function that checks for options
56176b2cf59SMatthew Knepley 
56276b2cf59SMatthew Knepley   Level: developer
56376b2cf59SMatthew Knepley 
5641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
56576b2cf59SMatthew Knepley @*/
566d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES))
567d71ae5a4SJacob Faibussowitsch {
56876b2cf59SMatthew Knepley   PetscFunctionBegin;
56963a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57076b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57276b2cf59SMatthew Knepley }
57376b2cf59SMatthew Knepley 
574d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
575d71ae5a4SJacob Faibussowitsch {
576aa3661deSLisandro Dalcin   Mat          J;
577895c21f2SBarry Smith   MatNullSpace nullsp;
578aa3661deSLisandro Dalcin 
579aa3661deSLisandro Dalcin   PetscFunctionBegin;
5800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
581aa3661deSLisandro Dalcin 
58298613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
58398613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5849566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
58598613b67SLisandro Dalcin   }
58698613b67SLisandro Dalcin 
5870fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
588aa3661deSLisandro Dalcin   if (version == 1) {
5899566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5909566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5919566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5921e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
5930fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
5945f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
595570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
596f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
597aa3661deSLisandro Dalcin #else
5982479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
599aa3661deSLisandro Dalcin #endif
6000fdf79fbSJacob Faibussowitsch   }
601aa3661deSLisandro Dalcin 
60201c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
603895c21f2SBarry Smith   if (snes->jacobian) {
6049566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6051baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
606895c21f2SBarry Smith   }
607895c21f2SBarry Smith 
60863a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
609d3462f78SMatthew Knepley   if (hasOperator) {
610aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
611aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6129566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
613aa3661deSLisandro Dalcin   } else {
614aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
61501c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
616b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6179566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
618172a4300SPeter Brune     } else {
619789d8953SBarry Smith       KSP       ksp;
620789d8953SBarry Smith       PC        pc;
621789d8953SBarry Smith       PetscBool match;
622789d8953SBarry Smith 
6239566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
624aa3661deSLisandro Dalcin       /* Force no preconditioner */
6259566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6269566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6272698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
628aa3661deSLisandro Dalcin       if (!match) {
6299566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6309566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
631aa3661deSLisandro Dalcin       }
632aa3661deSLisandro Dalcin     }
633789d8953SBarry Smith   }
6349566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
636aa3661deSLisandro Dalcin }
637aa3661deSLisandro Dalcin 
638d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
639d71ae5a4SJacob Faibussowitsch {
640dfe15315SJed Brown   SNES snes = (SNES)ctx;
6410298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
642dfe15315SJed Brown 
643dfe15315SJed Brown   PetscFunctionBegin;
64416ebb321SJed Brown   if (PetscLogPrintInfo) {
64516ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6469566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6479566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6489566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6499566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65063a3b9bcSJacob 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));
65116ebb321SJed Brown   }
652dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
653dfe15315SJed Brown   else {
6549566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
655dfe15315SJed Brown     Xfine = Xfine_named;
656dfe15315SJed Brown   }
6579566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
658907f5c5aSLawrence Mitchell   if (Inject) {
6599566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
660907f5c5aSLawrence Mitchell   } else {
6619566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6629566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
663907f5c5aSLawrence Mitchell   }
6649566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6659566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
667dfe15315SJed Brown }
668dfe15315SJed Brown 
669d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
670d71ae5a4SJacob Faibussowitsch {
67116ebb321SJed Brown   PetscFunctionBegin;
6729566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67416ebb321SJed Brown }
67516ebb321SJed Brown 
676a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
677a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
678d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
679d71ae5a4SJacob Faibussowitsch {
680caa4e7f2SJed Brown   SNES  snes = (SNES)ctx;
6810298fd71SBarry Smith   Vec   X, Xnamed = NULL;
682dfe15315SJed Brown   DM    dmsave;
6834e269d77SPeter Brune   void *ctxsave;
68425ce1634SJed Brown   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = NULL;
685caa4e7f2SJed Brown 
686caa4e7f2SJed Brown   PetscFunctionBegin;
687dfe15315SJed Brown   dmsave = snes->dm;
6889566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
689dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
6909371c9d4SSatish Balay   else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */ PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
691dfe15315SJed Brown     X = Xnamed;
6929566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
6934e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
69448a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
6954e269d77SPeter Brune   }
6964dde8bb0SMatthew G. Knepley   /* Make sure KSP DM has the Jacobian computation routine */
6974dde8bb0SMatthew G. Knepley   {
6984dde8bb0SMatthew G. Knepley     DMSNES sdm;
6994e269d77SPeter Brune 
7009566063dSJacob Faibussowitsch     PetscCall(DMGetDMSNES(snes->dm, &sdm));
70148a46eb9SPierre Jolivet     if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7024dde8bb0SMatthew G. Knepley   }
7032b93b426SMatthew G. Knepley   /* Compute the operators */
7049566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
7052b93b426SMatthew G. Knepley   /* Put the previous context back */
70648a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7074e269d77SPeter Brune 
7089566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
709dfe15315SJed Brown   snes->dm = dmsave;
7103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
711caa4e7f2SJed Brown }
712caa4e7f2SJed Brown 
7136cab3a1bSJed Brown /*@
714dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7156cab3a1bSJed Brown 
7166cab3a1bSJed Brown   Collective
7176cab3a1bSJed Brown 
7184165533cSJose E. Roman   Input Parameter:
71920f4b53cSBarry Smith . snes - `SNES` object to configure
7206cab3a1bSJed Brown 
7216cab3a1bSJed Brown   Level: developer
7226cab3a1bSJed Brown 
723dc4c0fb0SBarry Smith   Note:
724dc4c0fb0SBarry 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`
725dc4c0fb0SBarry Smith 
7261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7276cab3a1bSJed Brown @*/
728d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
729d71ae5a4SJacob Faibussowitsch {
7306cab3a1bSJed Brown   DM     dm;
731942e3340SBarry Smith   DMSNES sdm;
7326cab3a1bSJed Brown 
7336cab3a1bSJed Brown   PetscFunctionBegin;
7349566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7359566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
73658b371f3SBarry Smith   if (!snes->jacobian && snes->mf) {
7376cab3a1bSJed Brown     Mat   J;
7386cab3a1bSJed Brown     void *functx;
7399566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7409566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7419566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7429566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7439566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7449566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
745caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7466cab3a1bSJed Brown     Mat J, B;
7479566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7489566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7499566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7509566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
75106f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7529566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7539566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7549566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
755caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7561ba9b98eSMatthew G. Knepley     PetscDS   prob;
7576cab3a1bSJed Brown     Mat       J, B;
7581ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7591ba9b98eSMatthew G. Knepley 
7606cab3a1bSJed Brown     J = snes->jacobian;
7619566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7629566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7639566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7649566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7659566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7669566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7689566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7696cab3a1bSJed Brown   }
770caa4e7f2SJed Brown   {
771caa4e7f2SJed Brown     KSP ksp;
7729566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
7739566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
7749566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
775caa4e7f2SJed Brown   }
7763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7776cab3a1bSJed Brown }
7786cab3a1bSJed Brown 
779d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
780d71ae5a4SJacob Faibussowitsch {
7815e7c47f3SMatthew G. Knepley   PetscInt i;
7825e7c47f3SMatthew G. Knepley 
7835e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
7843ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
7855e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
7865e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
7875e7c47f3SMatthew G. Knepley     PetscDraw             draw;
7885e7c47f3SMatthew G. Knepley     PetscReal             lpause;
7895e7c47f3SMatthew G. Knepley 
7905e7c47f3SMatthew G. Knepley     if (!vf) continue;
7915e7c47f3SMatthew G. Knepley     if (vf->lg) {
7925e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
7935e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
7949566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
7959566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
7969566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
7979566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
7989566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
7995e7c47f3SMatthew G. Knepley     } else {
8005e7c47f3SMatthew G. Knepley       PetscBool isdraw;
8015e7c47f3SMatthew G. Knepley 
8025e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
8035e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
8049566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
8055e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
8069566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
8079566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8089566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8099566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8109566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8115e7c47f3SMatthew G. Knepley     }
8125e7c47f3SMatthew G. Knepley   }
8133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8145e7c47f3SMatthew G. Knepley }
8155e7c47f3SMatthew G. Knepley 
816fde5950dSBarry Smith /*@C
817fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
818fde5950dSBarry Smith 
819c3339decSBarry Smith   Collective
820fde5950dSBarry Smith 
821fde5950dSBarry Smith   Input Parameters:
822dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
823fde5950dSBarry Smith . name         - the monitor type one is seeking
824fde5950dSBarry Smith . help         - message indicating what monitoring is done
825fde5950dSBarry Smith . manual       - manual page for the monitor
826fde5950dSBarry Smith . monitor      - the monitor function
827f6dfbefdSBarry 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
828fde5950dSBarry Smith 
829f6dfbefdSBarry Smith   Options Database Key:
830f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
831f6dfbefdSBarry Smith 
832f6dfbefdSBarry Smith   Level: advanced
833fde5950dSBarry Smith 
8341cc06b55SBarry Smith .seealso: [](ch_snes), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
835db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
836e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
837db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
838c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
839db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
840db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
841fde5950dSBarry Smith @*/
842d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSetFromOptions(SNES snes, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNES, PetscInt, PetscReal, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(SNES, PetscViewerAndFormat *))
843d71ae5a4SJacob Faibussowitsch {
844fde5950dSBarry Smith   PetscViewer       viewer;
845fde5950dSBarry Smith   PetscViewerFormat format;
846fde5950dSBarry Smith   PetscBool         flg;
847fde5950dSBarry Smith 
848fde5950dSBarry Smith   PetscFunctionBegin;
8499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
850fde5950dSBarry Smith   if (flg) {
851d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8529566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
8539566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
8541baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8559566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
856fde5950dSBarry Smith   }
8573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
858fde5950dSBarry Smith }
859fde5950dSBarry Smith 
860a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
861d71ae5a4SJacob Faibussowitsch {
862a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
863a4598233SStefano Zampini 
8640f0abf79SStefano Zampini   PetscFunctionBegin;
8650f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
866a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
867a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
868a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
869a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
870a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
871a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
8720f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
873a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
8740f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8750f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8760f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8770f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8780f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8790f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8800f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8810f0abf79SStefano Zampini   PetscOptionsEnd();
8823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8830f0abf79SStefano Zampini }
8840f0abf79SStefano Zampini 
8859b94acceSBarry Smith /*@
886f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
8879b94acceSBarry Smith 
888c3339decSBarry Smith   Collective
889c7afd0dbSLois Curfman McInnes 
8909b94acceSBarry Smith   Input Parameter:
891f6dfbefdSBarry Smith . snes - the `SNES` context
8929b94acceSBarry Smith 
89336851e7fSLois Curfman McInnes   Options Database Keys:
894f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
895*ceaaa498SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
89670441072SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
897b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
898e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
899*ceaaa498SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
900b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
901b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
9024839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
903ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
904a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9053d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
906e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9073d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
9084a221d59SStefano Zampini . -snes_tr_tol <trtol>                                                         - trust region tolerance
909*ceaaa498SBarry 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.
910fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
911fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
912fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
913fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9144619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
915459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9165e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
917e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
918e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
919*ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
920b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
921*ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
922e62ac41dSBarry 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.
923e62ac41dSBarry 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.
92482738288SBarry Smith 
925f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
926fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9274b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
92836851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
92936851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
93036851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
93136851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
93236851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
93336851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
93482738288SBarry Smith 
935dc4c0fb0SBarry Smith   Level: beginner
936dc4c0fb0SBarry Smith 
93711ca99fdSLois Curfman McInnes   Notes:
938ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
939ec5066bdSBarry Smith 
94001c1178eSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free, and computing explicitly with
941f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
94283e2fdc7SBarry Smith 
9431cc06b55SBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`
9449b94acceSBarry Smith @*/
945d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
946d71ae5a4SJacob Faibussowitsch {
9478afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
948d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
94904d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
950649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
95185385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9520f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
953c40d0f55SPeter Brune   PCSide      pcside;
954a64e098fSPeter Brune   const char *optionsprefix;
9559b94acceSBarry Smith 
9563a40ed3dSBarry Smith   PetscFunctionBegin;
9570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9589566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
959d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
960639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
962d64ed03dSBarry Smith   if (flg) {
9639566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9647adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9659566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
966d64ed03dSBarry Smith   }
9679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
9689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
969186905e3SBarry Smith 
9709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
9719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
9729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
9739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
9749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
9759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
9769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
9779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
9789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
97985385478SLisandro Dalcin 
9809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
981a8054027SBarry Smith   if (flg) {
9825f80ce2aSJacob 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");
9839566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
984a8054027SBarry Smith   }
9859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
9861baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
9879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
988e35cf81dSBarry Smith   if (flg) {
9895f80ce2aSJacob 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");
9909566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
991e35cf81dSBarry Smith   }
9929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
9931baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
99437ec4e1aSPeter Brune 
9959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
9961baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
997a8054027SBarry Smith 
9989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, sizeof(convtests) / sizeof(char *), "default", &indx, &flg));
99985385478SLisandro Dalcin   if (flg) {
100085385478SLisandro Dalcin     switch (indx) {
1001d71ae5a4SJacob Faibussowitsch     case 0:
1002d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1003d71ae5a4SJacob Faibussowitsch       break;
1004d71ae5a4SJacob Faibussowitsch     case 1:
1005d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1006d71ae5a4SJacob Faibussowitsch       break;
1007d71ae5a4SJacob Faibussowitsch     case 2:
1008d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1009d71ae5a4SJacob Faibussowitsch       break;
101085385478SLisandro Dalcin     }
101185385478SLisandro Dalcin   }
101285385478SLisandro Dalcin 
10139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10149566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1015fdacfa88SPeter Brune 
10169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10179566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1018186905e3SBarry Smith 
101985385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
102085385478SLisandro Dalcin 
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1022186905e3SBarry Smith 
10230f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10240f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1025a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1026186905e3SBarry Smith 
102790d69ab7SBarry Smith   flg = PETSC_FALSE;
10289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10299566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1030eabae89aSBarry Smith 
10319566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10329566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10339566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1034eabae89aSBarry Smith 
10359566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10369566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10379566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10389566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10399566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10409566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10419566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10432db13446SMatthew G. Knepley 
10449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10459566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10465180491cSLisandro Dalcin 
104790d69ab7SBarry Smith   flg = PETSC_FALSE;
10489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1049459f5d12SBarry Smith   if (flg) {
1050459f5d12SBarry Smith     PetscViewer ctx;
1051e24b481bSBarry Smith 
10529566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10539566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1054459f5d12SBarry Smith   }
10552e7541e6SPeter Brune 
105690d69ab7SBarry Smith   flg = PETSC_FALSE;
10579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10589566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1059c4421ceaSFande Kong 
1060c4421ceaSFande Kong   flg = PETSC_FALSE;
10619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10624b27c08aSLois Curfman McInnes   if (flg) {
10636cab3a1bSJed Brown     void *functx;
1064b1f624c7SBarry Smith     DM    dm;
10659566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1066800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10679566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10689566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10699566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
10709b94acceSBarry Smith   }
1071639f9d9dSBarry Smith 
107244848bc4SPeter Brune   flg = PETSC_FALSE;
10739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
10741baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
107597584545SPeter Brune 
107697584545SPeter Brune   flg = PETSC_FALSE;
10779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
107844848bc4SPeter Brune   if (flg) {
1079c52e227fSPeter Brune     DM dm;
10809566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1081800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10829566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
10839566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
108444848bc4SPeter Brune   }
108544848bc4SPeter Brune 
1086aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1088d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1089a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1090d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1091a8248277SBarry Smith   }
1092aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1094d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
10959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1096d28543b3SPeter Brune 
1097c40d0f55SPeter Brune   flg = PETSC_FALSE;
10989566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
10999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11009566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1101c40d0f55SPeter Brune 
1102e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11038a70d858SHong Zhang   /*
11048a70d858SHong Zhang     Publish convergence information using SAWs
11058a70d858SHong Zhang   */
11068a70d858SHong Zhang   flg = PETSC_FALSE;
11079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11088a70d858SHong Zhang   if (flg) {
11098a70d858SHong Zhang     void *ctx;
11109566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11119566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11128a70d858SHong Zhang   }
11138a70d858SHong Zhang #endif
11148a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1115b90c6cbeSBarry Smith   {
1116b90c6cbeSBarry Smith     PetscBool set;
1117b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11189566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11191baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1120b90c6cbeSBarry Smith   }
1121b90c6cbeSBarry Smith #endif
1122b90c6cbeSBarry Smith 
112348a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
112476b2cf59SMatthew Knepley 
1125dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11265d973c19SBarry Smith 
11275d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1128dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1129d0609cedSBarry Smith   PetscOptionsEnd();
11304bbc92c1SBarry Smith 
1131d8d34be6SBarry Smith   if (snes->linesearch) {
11329566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11339566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1134d8d34be6SBarry Smith   }
11359e764e56SPeter Brune 
11366aa5e7e9SBarry Smith   if (snes->usesksp) {
11379566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11389566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11399566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11406aa5e7e9SBarry Smith   }
11416991f827SBarry Smith 
1142b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11439566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
114548a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11461baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1147b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1149b3cd9a81SMatthew G. Knepley }
1150b3cd9a81SMatthew G. Knepley 
1151b3cd9a81SMatthew G. Knepley /*@
1152f6dfbefdSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously set from options
1153b3cd9a81SMatthew G. Knepley 
1154c3339decSBarry Smith   Collective
1155b3cd9a81SMatthew G. Knepley 
1156b3cd9a81SMatthew G. Knepley   Input Parameter:
1157f6dfbefdSBarry Smith . snes - the `SNES` context
1158b3cd9a81SMatthew G. Knepley 
1159b3cd9a81SMatthew G. Knepley   Level: beginner
1160b3cd9a81SMatthew G. Knepley 
11611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1162b3cd9a81SMatthew G. Knepley @*/
1163d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1164d71ae5a4SJacob Faibussowitsch {
1165b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11669566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11689b94acceSBarry Smith }
11699b94acceSBarry Smith 
1170bb9467b5SJed Brown /*@C
1171d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1172d25893d9SBarry Smith   the nonlinear solvers.
1173d25893d9SBarry Smith 
1174dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1175d25893d9SBarry Smith 
1176d25893d9SBarry Smith   Input Parameters:
1177f6dfbefdSBarry Smith + snes    - the `SNES` context
1178d25893d9SBarry Smith . compute - function to compute the context
1179d25893d9SBarry Smith - destroy - function to destroy the context
1180d25893d9SBarry Smith 
1181d25893d9SBarry Smith   Level: intermediate
1182d25893d9SBarry Smith 
1183f6dfbefdSBarry Smith   Note:
1184f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1185f6dfbefdSBarry Smith 
1186f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1187f6dfbefdSBarry Smith 
118842747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`
1189d25893d9SBarry Smith @*/
1190d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES, void **), PetscErrorCode (*destroy)(void **))
1191d71ae5a4SJacob Faibussowitsch {
1192d25893d9SBarry Smith   PetscFunctionBegin;
1193d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1194d25893d9SBarry Smith   snes->ops->usercompute = compute;
1195d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
11963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1197d25893d9SBarry Smith }
1198a847f771SSatish Balay 
1199b07ff414SBarry Smith /*@
1200f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12019b94acceSBarry Smith 
1202c3339decSBarry Smith   Logically Collective
1203fee21e36SBarry Smith 
1204c7afd0dbSLois Curfman McInnes   Input Parameters:
1205f6dfbefdSBarry Smith + snes - the `SNES` context
1206c7afd0dbSLois Curfman McInnes - usrP - optional user context
1207c7afd0dbSLois Curfman McInnes 
120836851e7fSLois Curfman McInnes   Level: intermediate
120936851e7fSLois Curfman McInnes 
1210f6dfbefdSBarry Smith   Notes:
1211f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1212f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1213f6dfbefdSBarry Smith 
1214f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1215f6dfbefdSBarry Smith 
1216e4094ef1SJacob Faibussowitsch   Fortran Notes:
1217dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1218daf670e6SBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1219daf670e6SBarry Smith 
12201cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12219b94acceSBarry Smith @*/
1222d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1223d71ae5a4SJacob Faibussowitsch {
1224b07ff414SBarry Smith   KSP ksp;
12251b2093e4SBarry Smith 
12263a40ed3dSBarry Smith   PetscFunctionBegin;
12270700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12289566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12299566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12309b94acceSBarry Smith   snes->user = usrP;
12313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12329b94acceSBarry Smith }
123374679c65SBarry Smith 
1234b07ff414SBarry Smith /*@
12359b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1236f6dfbefdSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or with `SNESSetComputeApplicationContext()`
12379b94acceSBarry Smith 
1238c7afd0dbSLois Curfman McInnes   Not Collective
1239c7afd0dbSLois Curfman McInnes 
12409b94acceSBarry Smith   Input Parameter:
1241f6dfbefdSBarry Smith . snes - `SNES` context
12429b94acceSBarry Smith 
12439b94acceSBarry Smith   Output Parameter:
12449b94acceSBarry Smith . usrP - user context
12459b94acceSBarry Smith 
124636851e7fSLois Curfman McInnes   Level: intermediate
124736851e7fSLois Curfman McInnes 
1248e4094ef1SJacob Faibussowitsch   Fortran Notes:
1249dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1250dc4c0fb0SBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1251dc4c0fb0SBarry Smith 
12521cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`
12539b94acceSBarry Smith @*/
1254d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1255d71ae5a4SJacob Faibussowitsch {
12563a40ed3dSBarry Smith   PetscFunctionBegin;
12570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1258e71120c6SJed Brown   *(void **)usrP = snes->user;
12593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12609b94acceSBarry Smith }
126174679c65SBarry Smith 
12629b94acceSBarry Smith /*@
126301c1178eSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix vector products to apply the Jacobian.
12643565c898SBarry Smith 
1265dc4c0fb0SBarry Smith   Logically Collective
12663565c898SBarry Smith 
12673565c898SBarry Smith   Input Parameters:
1268f6dfbefdSBarry Smith + snes        - `SNES` context
1269f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1270f6dfbefdSBarry 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
1271f6dfbefdSBarry Smith    this option no matrix element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
12723565c898SBarry Smith 
1273f6dfbefdSBarry Smith   Options Database Keys:
127401c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1275f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1276ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1277ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
12783565c898SBarry Smith 
12793565c898SBarry Smith   Level: intermediate
12803565c898SBarry Smith 
1281f6dfbefdSBarry Smith   Note:
1282dc4c0fb0SBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free, and computing explicitly with
1283f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1284ec5066bdSBarry Smith 
12851cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`
12863565c898SBarry Smith @*/
1287d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1288d71ae5a4SJacob Faibussowitsch {
12893565c898SBarry Smith   PetscFunctionBegin;
12903565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
129188b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
129288b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
12934ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
12943565c898SBarry Smith   snes->mf_operator = mf_operator;
12953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12963565c898SBarry Smith }
12973565c898SBarry Smith 
12983565c898SBarry Smith /*@
1299dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13003565c898SBarry Smith 
1301f6dfbefdSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI ranks
13023565c898SBarry Smith 
13033565c898SBarry Smith   Input Parameter:
1304f6dfbefdSBarry Smith . snes - `SNES` context
13053565c898SBarry Smith 
13063565c898SBarry Smith   Output Parameters:
1307f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1308f6dfbefdSBarry 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
13093565c898SBarry Smith 
13103565c898SBarry Smith   Level: intermediate
13113565c898SBarry Smith 
13121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13133565c898SBarry Smith @*/
1314d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1315d71ae5a4SJacob Faibussowitsch {
13163565c898SBarry Smith   PetscFunctionBegin;
13173565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13183565c898SBarry Smith   if (mf) *mf = snes->mf;
13193565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13213565c898SBarry Smith }
13223565c898SBarry Smith 
13233565c898SBarry Smith /*@
1324c8228a4eSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed
1325c8228a4eSBarry Smith   at this time.
13269b94acceSBarry Smith 
1327c7afd0dbSLois Curfman McInnes   Not Collective
1328c7afd0dbSLois Curfman McInnes 
13299b94acceSBarry Smith   Input Parameter:
1330f6dfbefdSBarry Smith . snes - `SNES` context
13319b94acceSBarry Smith 
13329b94acceSBarry Smith   Output Parameter:
13339b94acceSBarry Smith . iter - iteration number
13349b94acceSBarry Smith 
1335dc4c0fb0SBarry Smith   Level: intermediate
1336dc4c0fb0SBarry Smith 
1337c8228a4eSBarry Smith   Notes:
1338c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1339c8228a4eSBarry Smith 
1340c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1341f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
134208405cd6SLois Curfman McInnes .vb
134308405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
134408405cd6SLois Curfman McInnes       if (!(it % 2)) {
134508405cd6SLois Curfman McInnes         [compute Jacobian here]
134608405cd6SLois Curfman McInnes       }
134708405cd6SLois Curfman McInnes .ve
1348f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1349f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1350c8228a4eSBarry Smith 
1351f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1352c04deec6SBarry Smith 
13531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`
13549b94acceSBarry Smith @*/
1355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1356d71ae5a4SJacob Faibussowitsch {
13573a40ed3dSBarry Smith   PetscFunctionBegin;
13580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13594f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
13609b94acceSBarry Smith   *iter = snes->iter;
13613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13629b94acceSBarry Smith }
136374679c65SBarry Smith 
1364360c497dSPeter Brune /*@
1365360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1366360c497dSPeter Brune 
1367360c497dSPeter Brune   Not Collective
1368360c497dSPeter Brune 
1369d8d19677SJose E. Roman   Input Parameters:
1370f6dfbefdSBarry Smith + snes - `SNES` context
1371a2b725a8SWilliam Gropp - iter - iteration number
1372360c497dSPeter Brune 
1373360c497dSPeter Brune   Level: developer
1374360c497dSPeter Brune 
13751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1376360c497dSPeter Brune @*/
1377d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1378d71ae5a4SJacob Faibussowitsch {
1379360c497dSPeter Brune   PetscFunctionBegin;
1380360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1382360c497dSPeter Brune   snes->iter = iter;
13839566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
13843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1385360c497dSPeter Brune }
1386360c497dSPeter Brune 
13879b94acceSBarry Smith /*@
1388b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
13899b94acceSBarry Smith   attempted by the nonlinear solver.
13909b94acceSBarry Smith 
1391c7afd0dbSLois Curfman McInnes   Not Collective
1392c7afd0dbSLois Curfman McInnes 
13939b94acceSBarry Smith   Input Parameter:
1394f6dfbefdSBarry Smith . snes - `SNES` context
13959b94acceSBarry Smith 
13969b94acceSBarry Smith   Output Parameter:
13979b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
13989b94acceSBarry Smith 
1399dc4c0fb0SBarry Smith   Level: intermediate
1400dc4c0fb0SBarry Smith 
1401f6dfbefdSBarry Smith   Note:
1402f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1403c96a6f78SLois Curfman McInnes 
14041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1405db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14069b94acceSBarry Smith @*/
1407d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1408d71ae5a4SJacob Faibussowitsch {
14093a40ed3dSBarry Smith   PetscFunctionBegin;
14100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14114f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
141250ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
141450ffb88aSMatthew Knepley }
141550ffb88aSMatthew Knepley 
141650ffb88aSMatthew Knepley /*@
1417b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1418f6dfbefdSBarry Smith   attempted by the nonlinear solver before it gives up and generates an error
141950ffb88aSMatthew Knepley 
142050ffb88aSMatthew Knepley   Not Collective
142150ffb88aSMatthew Knepley 
142250ffb88aSMatthew Knepley   Input Parameters:
1423f6dfbefdSBarry Smith + snes     - `SNES` context
142450ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps
142550ffb88aSMatthew Knepley 
142650ffb88aSMatthew Knepley   Level: intermediate
142750ffb88aSMatthew Knepley 
14281cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1429db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
143050ffb88aSMatthew Knepley @*/
1431d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1432d71ae5a4SJacob Faibussowitsch {
143350ffb88aSMatthew Knepley   PetscFunctionBegin;
14340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
143550ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
14363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143750ffb88aSMatthew Knepley }
143850ffb88aSMatthew Knepley 
143950ffb88aSMatthew Knepley /*@
1440b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1441f6dfbefdSBarry Smith   attempted by the nonlinear solver before it gives up and generates an error
144250ffb88aSMatthew Knepley 
144350ffb88aSMatthew Knepley   Not Collective
144450ffb88aSMatthew Knepley 
144550ffb88aSMatthew Knepley   Input Parameter:
144620f4b53cSBarry Smith . snes - `SNES` context
144750ffb88aSMatthew Knepley 
144850ffb88aSMatthew Knepley   Output Parameter:
144950ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
145050ffb88aSMatthew Knepley 
145150ffb88aSMatthew Knepley   Level: intermediate
145250ffb88aSMatthew Knepley 
14531cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1454db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
145550ffb88aSMatthew Knepley @*/
1456d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1457d71ae5a4SJacob Faibussowitsch {
145850ffb88aSMatthew Knepley   PetscFunctionBegin;
14590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14604f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
146150ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
14623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14639b94acceSBarry Smith }
1464a847f771SSatish Balay 
14652541af92SBarry Smith /*@
14662541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1467f6dfbefdSBarry Smith   done by the `SNES` object
14682541af92SBarry Smith 
14692541af92SBarry Smith   Not Collective
14702541af92SBarry Smith 
14712541af92SBarry Smith   Input Parameter:
1472f6dfbefdSBarry Smith . snes - `SNES` context
14732541af92SBarry Smith 
14742541af92SBarry Smith   Output Parameter:
14752541af92SBarry Smith . nfuncs - number of evaluations
14762541af92SBarry Smith 
14772541af92SBarry Smith   Level: intermediate
14782541af92SBarry Smith 
1479f6dfbefdSBarry Smith   Note:
1480f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1481971e163fSPeter Brune 
14821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
14832541af92SBarry Smith @*/
1484d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1485d71ae5a4SJacob Faibussowitsch {
14862541af92SBarry Smith   PetscFunctionBegin;
14870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14884f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
14892541af92SBarry Smith   *nfuncs = snes->nfuncs;
14903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14912541af92SBarry Smith }
14922541af92SBarry Smith 
14933d4c4710SBarry Smith /*@
14943d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
14953d4c4710SBarry Smith   linear solvers.
14963d4c4710SBarry Smith 
14973d4c4710SBarry Smith   Not Collective
14983d4c4710SBarry Smith 
14993d4c4710SBarry Smith   Input Parameter:
1500f6dfbefdSBarry Smith . snes - `SNES` context
15013d4c4710SBarry Smith 
15023d4c4710SBarry Smith   Output Parameter:
15033d4c4710SBarry Smith . nfails - number of failed solves
15043d4c4710SBarry Smith 
1505f6dfbefdSBarry Smith   Options Database Key:
15069d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15079d85da0cSMatthew G. Knepley 
1508f6dfbefdSBarry Smith   Level: intermediate
1509f6dfbefdSBarry Smith 
1510f6dfbefdSBarry Smith   Note:
1511f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15123d4c4710SBarry Smith 
15131cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15143d4c4710SBarry Smith @*/
1515d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1516d71ae5a4SJacob Faibussowitsch {
15173d4c4710SBarry Smith   PetscFunctionBegin;
15180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15194f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15203d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15223d4c4710SBarry Smith }
15233d4c4710SBarry Smith 
15243d4c4710SBarry Smith /*@
15253d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1526f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15273d4c4710SBarry Smith 
1528c3339decSBarry Smith   Logically Collective
15293d4c4710SBarry Smith 
15303d4c4710SBarry Smith   Input Parameters:
1531f6dfbefdSBarry Smith + snes     - `SNES` context
15323d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures
15333d4c4710SBarry Smith 
1534f6dfbefdSBarry Smith   Options Database Key:
15359d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15369d85da0cSMatthew G. Knepley 
1537dc4c0fb0SBarry Smith   Level: intermediate
1538dc4c0fb0SBarry Smith 
1539f6dfbefdSBarry Smith   Note:
1540f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
15413d4c4710SBarry Smith 
15421cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
15433d4c4710SBarry Smith @*/
1544d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1545d71ae5a4SJacob Faibussowitsch {
15463d4c4710SBarry Smith   PetscFunctionBegin;
15470700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1548c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
15493d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
15503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15513d4c4710SBarry Smith }
15523d4c4710SBarry Smith 
15533d4c4710SBarry Smith /*@
15543d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1555f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
15563d4c4710SBarry Smith 
15573d4c4710SBarry Smith   Not Collective
15583d4c4710SBarry Smith 
15593d4c4710SBarry Smith   Input Parameter:
1560f6dfbefdSBarry Smith . snes - `SNES` context
15613d4c4710SBarry Smith 
15623d4c4710SBarry Smith   Output Parameter:
15633d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
15643d4c4710SBarry Smith 
15653d4c4710SBarry Smith   Level: intermediate
15663d4c4710SBarry Smith 
1567f6dfbefdSBarry Smith   Note:
1568f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
15693d4c4710SBarry Smith 
15701cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
15713d4c4710SBarry Smith @*/
1572d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1573d71ae5a4SJacob Faibussowitsch {
15743d4c4710SBarry Smith   PetscFunctionBegin;
15750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15764f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
15773d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
15783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15793d4c4710SBarry Smith }
15803d4c4710SBarry Smith 
1581c96a6f78SLois Curfman McInnes /*@
1582b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1583c96a6f78SLois Curfman McInnes   used by the nonlinear solver.
1584c96a6f78SLois Curfman McInnes 
1585c7afd0dbSLois Curfman McInnes   Not Collective
1586c7afd0dbSLois Curfman McInnes 
1587c96a6f78SLois Curfman McInnes   Input Parameter:
1588f6dfbefdSBarry Smith . snes - `SNES` context
1589c96a6f78SLois Curfman McInnes 
1590c96a6f78SLois Curfman McInnes   Output Parameter:
1591c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1592c96a6f78SLois Curfman McInnes 
1593dc4c0fb0SBarry Smith   Level: intermediate
1594dc4c0fb0SBarry Smith 
1595c96a6f78SLois Curfman McInnes   Notes:
1596f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1597c96a6f78SLois Curfman McInnes 
1598f6dfbefdSBarry 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
1599f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1600010be392SBarry Smith 
16011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1602c96a6f78SLois Curfman McInnes @*/
1603d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1604d71ae5a4SJacob Faibussowitsch {
16053a40ed3dSBarry Smith   PetscFunctionBegin;
16060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16074f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1608c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1610c96a6f78SLois Curfman McInnes }
1611c96a6f78SLois Curfman McInnes 
1612971e163fSPeter Brune /*@
1613971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1614f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1615971e163fSPeter Brune 
1616c3339decSBarry Smith   Logically Collective
1617971e163fSPeter Brune 
1618d8d19677SJose E. Roman   Input Parameters:
1619f6dfbefdSBarry Smith + snes  - `SNES` context
1620f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1621971e163fSPeter Brune 
1622971e163fSPeter Brune   Level: developer
1623971e163fSPeter Brune 
16241cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1625971e163fSPeter Brune @*/
1626d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1627d71ae5a4SJacob Faibussowitsch {
1628971e163fSPeter Brune   PetscFunctionBegin;
1629971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1630971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1631971e163fSPeter Brune   snes->counters_reset = reset;
16323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1633971e163fSPeter Brune }
1634971e163fSPeter Brune 
16352999313aSBarry Smith /*@
1636f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16372999313aSBarry Smith 
1638f6dfbefdSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same MPI_Comm
16392999313aSBarry Smith 
16402999313aSBarry Smith   Input Parameters:
1641f6dfbefdSBarry Smith + snes - the `SNES` context
1642f6dfbefdSBarry Smith - ksp  - the `KSP` context
16432999313aSBarry Smith 
1644dc4c0fb0SBarry Smith   Level: developer
1645dc4c0fb0SBarry Smith 
16462999313aSBarry Smith   Notes:
1647f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
16482999313aSBarry Smith   so this routine is rarely needed.
16492999313aSBarry Smith 
1650f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
16512999313aSBarry Smith   decreased by one.
16522999313aSBarry Smith 
165342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
16542999313aSBarry Smith @*/
1655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1656d71ae5a4SJacob Faibussowitsch {
16572999313aSBarry Smith   PetscFunctionBegin;
16580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16590700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
16602999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
16619566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
16629566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
16632999313aSBarry Smith   snes->ksp = ksp;
16643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16652999313aSBarry Smith }
16662999313aSBarry Smith 
166752baeb72SSatish Balay /*@
1668dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
16699b94acceSBarry Smith 
1670d083f849SBarry Smith   Collective
1671c7afd0dbSLois Curfman McInnes 
1672f6dfbefdSBarry Smith   Input Parameter:
1673906ed7ccSBarry Smith . comm - MPI communicator
16749b94acceSBarry Smith 
16759b94acceSBarry Smith   Output Parameter:
167620f4b53cSBarry Smith . outsnes - the new `SNES` context
16779b94acceSBarry Smith 
1678c7afd0dbSLois Curfman McInnes   Options Database Keys:
1679dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1680dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1681dc4c0fb0SBarry Smith                as set by `SNESSetJacobian()`
1682dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1683c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1684c1f60f51SBarry Smith 
168536851e7fSLois Curfman McInnes   Level: beginner
168636851e7fSLois Curfman McInnes 
168795452b02SPatrick Sanan   Developer Notes:
1688f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1689efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1690f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1691f6dfbefdSBarry Smith   in `SNESView()`.
1692efd4aadfSBarry Smith 
1693f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1694f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1695f6dfbefdSBarry Smith 
1696dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1697efd4aadfSBarry Smith 
1698e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
16999b94acceSBarry Smith @*/
1700d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1701d71ae5a4SJacob Faibussowitsch {
17029b94acceSBarry Smith   SNES       snes;
1703fa9f3622SBarry Smith   SNESKSPEW *kctx;
170437fcc0dbSBarry Smith 
17053a40ed3dSBarry Smith   PetscFunctionBegin;
17064f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
17070298fd71SBarry Smith   *outsnes = NULL;
17089566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17098ba1e511SMatthew Knepley 
17109566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17117adad957SLisandro Dalcin 
17128d359177SBarry Smith   snes->ops->converged       = SNESConvergedDefault;
17132c155ee1SBarry Smith   snes->usesksp              = PETSC_TRUE;
171488976e71SPeter Brune   snes->tolerancesset        = PETSC_FALSE;
17159b94acceSBarry Smith   snes->max_its              = 50;
17169750a799SBarry Smith   snes->max_funcs            = 10000;
17179b94acceSBarry Smith   snes->norm                 = 0.0;
1718c1e67a49SFande Kong   snes->xnorm                = 0.0;
1719c1e67a49SFande Kong   snes->ynorm                = 0.0;
1720365a6726SPeter Brune   snes->normschedule         = SNES_NORM_ALWAYS;
17216c67d002SPeter Brune   snes->functype             = SNES_FUNCTION_DEFAULT;
17228ca48ce9SPierre Jolivet   snes->rtol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
1723b4874afaSBarry Smith   snes->ttol                 = 0.0;
17248ca48ce9SPierre Jolivet   snes->abstol               = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50;
17258ca48ce9SPierre Jolivet   snes->stol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
17268ca48ce9SPierre Jolivet   snes->deltatol             = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12;
1727e37c518bSBarry Smith   snes->divtol               = 1.e4;
1728e37c518bSBarry Smith   snes->rnorm0               = 0;
17299b94acceSBarry Smith   snes->nfuncs               = 0;
173050ffb88aSMatthew Knepley   snes->numFailures          = 0;
173150ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17327a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1733e35cf81dSBarry Smith   snes->lagjacobian          = 1;
173437ec4e1aSPeter Brune   snes->jac_iter             = 0;
173537ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1736a8054027SBarry Smith   snes->lagpreconditioner    = 1;
173737ec4e1aSPeter Brune   snes->pre_iter             = 0;
173837ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1739639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1740c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17419e5d0892SLisandro Dalcin   snes->data                 = NULL;
17424dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1743186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17446f24a144SLois Curfman McInnes   snes->nwork                = 0;
17459e5d0892SLisandro Dalcin   snes->work                 = NULL;
174658c9b817SLisandro Dalcin   snes->nvwork               = 0;
17479e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1748758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1749758f92a0SBarry Smith   snes->conv_hist_max        = 0;
17500298fd71SBarry Smith   snes->conv_hist            = NULL;
17510298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1752758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1753971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1754e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1755184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1756efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1757b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1758c40d0f55SPeter Brune 
1759d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1760d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1761d8f46077SPeter Brune   snes->mf_version  = 1;
1762d8f46077SPeter Brune 
17633d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
17643d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
17653d4c4710SBarry Smith 
1766349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
176776bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1768349187a7SBarry Smith 
17694fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
17704fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
17714fc747eaSLawrence Mitchell 
17729b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
17734dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1774f5af7f23SKarl Rupp 
17759b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
17769b94acceSBarry Smith   kctx->version     = 2;
17770f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
17789b94acceSBarry Smith                              this was too large for some test cases */
177975567043SBarry Smith   kctx->rtol_last   = 0.0;
17800f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
17819b94acceSBarry Smith   kctx->gamma       = 1.0;
17820f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
178371f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
17840f0abf79SStefano Zampini   kctx->threshold   = 0.1;
178575567043SBarry Smith   kctx->lresid_last = 0.0;
178675567043SBarry Smith   kctx->norm_last   = 0.0;
17879b94acceSBarry Smith 
17880f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
17890f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
17900f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
17910f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
17920f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
17930f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
17940f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
17950f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
17960f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
17970f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
17980f0abf79SStefano Zampini 
17999b94acceSBarry Smith   *outsnes = snes;
18003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18019b94acceSBarry Smith }
18029b94acceSBarry Smith 
180388f0584fSBarry Smith /*MC
1804f6dfbefdSBarry Smith     SNESFunction - Functional form used to convey the nonlinear function to `SNES` in `SNESSetFunction()`
180588f0584fSBarry Smith 
180688f0584fSBarry Smith      Synopsis:
1807411c0326SBarry Smith      #include "petscsnes.h"
1808411c0326SBarry Smith      PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
180988f0584fSBarry Smith 
1810c3339decSBarry Smith      Collective
18111843f636SBarry Smith 
181288f0584fSBarry Smith      Input Parameters:
1813f6dfbefdSBarry Smith +     snes - the `SNES` context
181488f0584fSBarry Smith .     x    - state at which to evaluate residual
1815f6dfbefdSBarry Smith -     ctx     - optional user-defined function context, passed in with `SNESSetFunction()`
181688f0584fSBarry Smith 
181788f0584fSBarry Smith      Output Parameter:
181888f0584fSBarry Smith .     f  - vector to put residual (function value)
181988f0584fSBarry Smith 
1820878cb397SSatish Balay    Level: intermediate
1821878cb397SSatish Balay 
18221cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESGetFunction()`
182388f0584fSBarry Smith M*/
182488f0584fSBarry Smith 
18259b94acceSBarry Smith /*@C
18269b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1827f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
18289b94acceSBarry Smith   equations.
18299b94acceSBarry Smith 
1830c3339decSBarry Smith   Logically Collective
1831fee21e36SBarry Smith 
1832c7afd0dbSLois Curfman McInnes   Input Parameters:
1833f6dfbefdSBarry Smith + snes - the `SNES` context
1834dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
183520f4b53cSBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunction`
1836c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1837dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
18389b94acceSBarry Smith 
183936851e7fSLois Curfman McInnes   Level: beginner
184036851e7fSLois Curfman McInnes 
18411cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunction`
18429b94acceSBarry Smith @*/
1843d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunction(SNES snes, Vec r, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
1844d71ae5a4SJacob Faibussowitsch {
18456cab3a1bSJed Brown   DM dm;
18466cab3a1bSJed Brown 
18473a40ed3dSBarry Smith   PetscFunctionBegin;
18480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1849d2a683ecSLisandro Dalcin   if (r) {
1850d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1851d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18529566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18539566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
185485385478SLisandro Dalcin     snes->vec_func = r;
1855d2a683ecSLisandro Dalcin   }
18569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18579566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
185848a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18609b94acceSBarry Smith }
18619b94acceSBarry Smith 
1862e4ed7901SPeter Brune /*@C
18630b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1864e4ed7901SPeter Brune 
1865c3339decSBarry Smith   Logically Collective
1866e4ed7901SPeter Brune 
1867e4ed7901SPeter Brune   Input Parameters:
1868f6dfbefdSBarry Smith + snes - the `SNES` context
1869e4ed7901SPeter Brune - f    - vector to store function value
1870e4ed7901SPeter Brune 
1871dc4c0fb0SBarry Smith   Level: developer
1872dc4c0fb0SBarry Smith 
1873e4ed7901SPeter Brune   Notes:
1874e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1875e4ed7901SPeter Brune 
1876f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1877e4ed7901SPeter Brune 
18781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1879e4ed7901SPeter Brune @*/
1880d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1881d71ae5a4SJacob Faibussowitsch {
1882e4ed7901SPeter Brune   Vec vec_func;
1883e4ed7901SPeter Brune 
1884e4ed7901SPeter Brune   PetscFunctionBegin;
1885e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1886e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1887e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1888efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1889902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
18903ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1891902f982fSPeter Brune   }
18929566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
18939566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1894f5af7f23SKarl Rupp 
1895217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
18963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1897e4ed7901SPeter Brune }
1898e4ed7901SPeter Brune 
1899534ebe21SPeter Brune /*@
1900f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1901f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1902534ebe21SPeter Brune 
1903c3339decSBarry Smith   Logically Collective
1904534ebe21SPeter Brune 
1905534ebe21SPeter Brune   Input Parameters:
1906f6dfbefdSBarry Smith + snes         - the `SNES` context
1907365a6726SPeter Brune - normschedule - the frequency of norm computation
1908534ebe21SPeter Brune 
1909517f1916SMatthew G. Knepley   Options Database Key:
191067b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1911517f1916SMatthew G. Knepley 
1912dc4c0fb0SBarry Smith   Level: advanced
1913dc4c0fb0SBarry Smith 
1914534ebe21SPeter Brune   Notes:
1915f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1916534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
1917534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1918f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1919534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
1920534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
1921534ebe21SPeter Brune   their solution.
1922534ebe21SPeter Brune 
1923e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
1924534ebe21SPeter Brune @*/
1925d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1926d71ae5a4SJacob Faibussowitsch {
1927534ebe21SPeter Brune   PetscFunctionBegin;
1928534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1929365a6726SPeter Brune   snes->normschedule = normschedule;
19303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1931534ebe21SPeter Brune }
1932534ebe21SPeter Brune 
1933534ebe21SPeter Brune /*@
1934f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1935f6dfbefdSBarry Smith   of the `SNES` method.
1936534ebe21SPeter Brune 
1937c3339decSBarry Smith   Logically Collective
1938534ebe21SPeter Brune 
1939534ebe21SPeter Brune   Input Parameters:
1940f6dfbefdSBarry Smith + snes         - the `SNES` context
1941365a6726SPeter Brune - normschedule - the type of the norm used
1942534ebe21SPeter Brune 
1943534ebe21SPeter Brune   Level: advanced
1944534ebe21SPeter Brune 
19451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1946534ebe21SPeter Brune @*/
1947d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1948d71ae5a4SJacob Faibussowitsch {
1949534ebe21SPeter Brune   PetscFunctionBegin;
1950534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1951365a6726SPeter Brune   *normschedule = snes->normschedule;
19523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1953534ebe21SPeter Brune }
1954534ebe21SPeter Brune 
1955c5ce4427SMatthew G. Knepley /*@
1956c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1957c5ce4427SMatthew G. Knepley 
1958c3339decSBarry Smith   Logically Collective
1959c5ce4427SMatthew G. Knepley 
1960c5ce4427SMatthew G. Knepley   Input Parameters:
1961f6dfbefdSBarry Smith + snes - the `SNES` context
1962f6dfbefdSBarry Smith - norm - the value of the norm
1963c5ce4427SMatthew G. Knepley 
1964c5ce4427SMatthew G. Knepley   Level: developer
1965c5ce4427SMatthew G. Knepley 
19661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1967c5ce4427SMatthew G. Knepley @*/
1968d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1969d71ae5a4SJacob Faibussowitsch {
1970c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1971c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1972c5ce4427SMatthew G. Knepley   snes->norm = norm;
19733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1974c5ce4427SMatthew G. Knepley }
1975c5ce4427SMatthew G. Knepley 
1976c5ce4427SMatthew G. Knepley /*@
1977c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
1978c5ce4427SMatthew G. Knepley 
1979c5ce4427SMatthew G. Knepley   Not Collective
1980c5ce4427SMatthew G. Knepley 
1981c5ce4427SMatthew G. Knepley   Input Parameter:
1982f6dfbefdSBarry Smith . snes - the `SNES` context
1983c5ce4427SMatthew G. Knepley 
1984c5ce4427SMatthew G. Knepley   Output Parameter:
1985c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
1986c5ce4427SMatthew G. Knepley 
1987c5ce4427SMatthew G. Knepley   Level: developer
1988c5ce4427SMatthew G. Knepley 
19891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1990c5ce4427SMatthew G. Knepley @*/
1991d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
1992d71ae5a4SJacob Faibussowitsch {
1993c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1994c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
19954f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
1996c5ce4427SMatthew G. Knepley   *norm = snes->norm;
19973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1998c5ce4427SMatthew G. Knepley }
1999c5ce4427SMatthew G. Knepley 
2000c1e67a49SFande Kong /*@
2001f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2002c1e67a49SFande Kong 
2003c1e67a49SFande Kong   Not Collective
2004c1e67a49SFande Kong 
2005c1e67a49SFande Kong   Input Parameter:
2006f6dfbefdSBarry Smith . snes - the `SNES` context
2007c1e67a49SFande Kong 
2008c1e67a49SFande Kong   Output Parameter:
2009c1e67a49SFande Kong . ynorm - the last computed update norm
2010c1e67a49SFande Kong 
2011c1e67a49SFande Kong   Level: developer
2012c1e67a49SFande Kong 
2013f6dfbefdSBarry Smith   Note:
2014f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2015f6dfbefdSBarry Smith 
20161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2017c1e67a49SFande Kong @*/
2018d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2019d71ae5a4SJacob Faibussowitsch {
2020c1e67a49SFande Kong   PetscFunctionBegin;
2021c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20224f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2023c1e67a49SFande Kong   *ynorm = snes->ynorm;
20243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2025c1e67a49SFande Kong }
2026c1e67a49SFande Kong 
2027c1e67a49SFande Kong /*@
20284591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2029c1e67a49SFande Kong 
2030c1e67a49SFande Kong   Not Collective
2031c1e67a49SFande Kong 
2032c1e67a49SFande Kong   Input Parameter:
2033f6dfbefdSBarry Smith . snes - the `SNES` context
2034c1e67a49SFande Kong 
2035c1e67a49SFande Kong   Output Parameter:
2036c1e67a49SFande Kong . xnorm - the last computed solution norm
2037c1e67a49SFande Kong 
2038c1e67a49SFande Kong   Level: developer
2039c1e67a49SFande Kong 
20401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2041c1e67a49SFande Kong @*/
2042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2043d71ae5a4SJacob Faibussowitsch {
2044c1e67a49SFande Kong   PetscFunctionBegin;
2045c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20464f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2047c1e67a49SFande Kong   *xnorm = snes->xnorm;
20483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2049c1e67a49SFande Kong }
2050c1e67a49SFande Kong 
205147073ea2SPeter Brune /*@C
2052f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2053f6dfbefdSBarry Smith   of the `SNES` method.
205447073ea2SPeter Brune 
2055c3339decSBarry Smith   Logically Collective
205647073ea2SPeter Brune 
205747073ea2SPeter Brune   Input Parameters:
2058f6dfbefdSBarry Smith + snes - the `SNES` context
2059f6dfbefdSBarry Smith - type - the function type
206047073ea2SPeter Brune 
206147073ea2SPeter Brune   Level: developer
206247073ea2SPeter Brune 
2063f6dfbefdSBarry Smith   Notes:
2064f6dfbefdSBarry Smith   Possible values of the function type
2065f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType`
2066f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2067f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()`
2068f6dfbefdSBarry Smith 
2069f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2070f6dfbefdSBarry Smith 
20711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
207247073ea2SPeter Brune @*/
2073d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2074d71ae5a4SJacob Faibussowitsch {
207547073ea2SPeter Brune   PetscFunctionBegin;
207647073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
207747073ea2SPeter Brune   snes->functype = type;
20783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207947073ea2SPeter Brune }
208047073ea2SPeter Brune 
208147073ea2SPeter Brune /*@C
2082f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
208347073ea2SPeter Brune   of the SNES method.
208447073ea2SPeter Brune 
2085c3339decSBarry Smith   Logically Collective
208647073ea2SPeter Brune 
208747073ea2SPeter Brune   Input Parameters:
2088f6dfbefdSBarry Smith + snes - the `SNES` context
2089f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
209047073ea2SPeter Brune 
209147073ea2SPeter Brune   Level: advanced
209247073ea2SPeter Brune 
20931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
209447073ea2SPeter Brune @*/
2095d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2096d71ae5a4SJacob Faibussowitsch {
209747073ea2SPeter Brune   PetscFunctionBegin;
209847073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
209947073ea2SPeter Brune   *type = snes->functype;
21003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2101534ebe21SPeter Brune }
2102534ebe21SPeter Brune 
2103c79ef259SPeter Brune /*@C
2104be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2105c79ef259SPeter Brune   use with composed nonlinear solvers.
2106c79ef259SPeter Brune 
2107c79ef259SPeter Brune   Input Parameters:
2108dc4c0fb0SBarry Smith + snes - the `SNES` context
210937fdd005SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel
2110c79ef259SPeter Brune - ctx  - [optional] user-defined context for private data for the
2111dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2112c79ef259SPeter Brune 
211320f4b53cSBarry Smith   Calling sequence of `f`:
21140b4db180SJacob Faibussowitsch $ PetscErrorCode f(SNES snes, Vec X, Vec B, void *ctx);
2115f6dfbefdSBarry Smith + snes - the `SNES` context
2116f6dfbefdSBarry Smith . X    - the current solution
2117dc4c0fb0SBarry Smith . B    - the right hand side vector (which may be `NULL`)
2118f6dfbefdSBarry Smith - ctx  - a user provided context
2119f6dfbefdSBarry Smith 
2120dc4c0fb0SBarry Smith   Level: intermediate
2121dc4c0fb0SBarry Smith 
2122f6dfbefdSBarry Smith   Note:
2123f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2124f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2125c79ef259SPeter Brune 
21261cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`
2127c79ef259SPeter Brune @*/
21280b4db180SJacob Faibussowitsch PetscErrorCode SNESSetNGS(SNES snes, PetscErrorCode (*f)(SNES snes, Vec X, Vec B, void *ctx), void *ctx)
2129d71ae5a4SJacob Faibussowitsch {
21306cab3a1bSJed Brown   DM dm;
21316cab3a1bSJed Brown 
2132646217ecSPeter Brune   PetscFunctionBegin;
21336cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21349566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21359566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2137646217ecSPeter Brune }
2138646217ecSPeter Brune 
2139bbc1464cSBarry Smith /*
2140bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2141bbc1464cSBarry Smith    changed during the KSPSolve()
2142bbc1464cSBarry Smith */
2143d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2144d71ae5a4SJacob Faibussowitsch {
2145bbc1464cSBarry Smith   DM     dm;
2146bbc1464cSBarry Smith   DMSNES sdm;
2147bbc1464cSBarry Smith 
2148bbc1464cSBarry Smith   PetscFunctionBegin;
21499566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21509566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2151bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2152bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2153792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21549566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21550df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2156ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2157792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21589566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2159bbc1464cSBarry Smith   } else {
2160792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21619566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2162bbc1464cSBarry Smith   }
21633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2164bbc1464cSBarry Smith }
2165bbc1464cSBarry Smith 
2166d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2167d71ae5a4SJacob Faibussowitsch {
2168e03ab78fSPeter Brune   DM     dm;
2169942e3340SBarry Smith   DMSNES sdm;
21706cab3a1bSJed Brown 
21718b0a5094SBarry Smith   PetscFunctionBegin;
21729566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21739566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
21748b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2175bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2176792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21779566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2178792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
21799566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2180bbc1464cSBarry Smith   } else {
2181792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
21829566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2183bbc1464cSBarry Smith   }
21843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21858b0a5094SBarry Smith }
21868b0a5094SBarry Smith 
2187d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2188d71ae5a4SJacob Faibussowitsch {
21898b0a5094SBarry Smith   PetscFunctionBegin;
2190e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2191bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
21929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
21939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
21943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21958b0a5094SBarry Smith }
21968b0a5094SBarry Smith 
21978b0a5094SBarry Smith /*@C
2198f6dfbefdSBarry Smith   SNESSetPicard - Use `SNES` to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization)
21998b0a5094SBarry Smith 
2200c3339decSBarry Smith   Logically Collective
22018b0a5094SBarry Smith 
22028b0a5094SBarry Smith   Input Parameters:
2203f6dfbefdSBarry Smith + snes - the `SNES` context
2204dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
2205dc4c0fb0SBarry Smith . bp   - function evaluation routine, may be `NULL`
22066b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2207dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
220820f4b53cSBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFunction()`
2209dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2210dc4c0fb0SBarry Smith 
2211dc4c0fb0SBarry Smith   Level: intermediate
22128b0a5094SBarry Smith 
22138b0a5094SBarry Smith   Notes:
22146b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2215f450aa47SBarry 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.
2216f450aa47SBarry Smith 
2217f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22188b0a5094SBarry Smith 
2219dc4c0fb0SBarry 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}.
2220dc4c0fb0SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration.
22218b0a5094SBarry Smith 
2222dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22238b0a5094SBarry Smith 
22240d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22256b7fb656SBarry Smith   the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b
22268b0a5094SBarry Smith 
22278b0a5094SBarry 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
22288b0a5094SBarry 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
22298b0a5094SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
22308b0a5094SBarry Smith 
2231dc4c0fb0SBarry 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
2232f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
22336b7fb656SBarry Smith 
2234dc4c0fb0SBarry Smith   When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at at time) and thus represent Newton's method.
22356b7fb656SBarry Smith 
2236dc4c0fb0SBarry 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
22376b7fb656SBarry 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
2238f6dfbefdSBarry 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`.
2239aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2240bbc1464cSBarry Smith 
22411cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, `SNESJacobianFunction`
22428b0a5094SBarry Smith @*/
2243d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetPicard(SNES snes, Vec r, PetscErrorCode (*bp)(SNES, Vec, Vec, void *), Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx)
2244d71ae5a4SJacob Faibussowitsch {
2245e03ab78fSPeter Brune   DM dm;
2246e03ab78fSPeter Brune 
22478b0a5094SBarry Smith   PetscFunctionBegin;
22488b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22499566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22509566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22519566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22529566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22539566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22558b0a5094SBarry Smith }
22568b0a5094SBarry Smith 
22577971a8bfSPeter Brune /*@C
22587971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
22597971a8bfSPeter Brune 
2260f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
22617971a8bfSPeter Brune 
22627971a8bfSPeter Brune   Input Parameter:
2263f6dfbefdSBarry Smith . snes - the `SNES` context
22647971a8bfSPeter Brune 
2265d8d19677SJose E. Roman   Output Parameters:
2266dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
226720f4b53cSBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunction`
2268dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2269dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
227020f4b53cSBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFunction`
2271dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
22727971a8bfSPeter Brune 
22737971a8bfSPeter Brune   Level: advanced
22747971a8bfSPeter Brune 
22751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunction`, `SNESJacobianFunction`
22767971a8bfSPeter Brune @*/
2277d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetPicard(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx)
2278d71ae5a4SJacob Faibussowitsch {
22797971a8bfSPeter Brune   DM dm;
22807971a8bfSPeter Brune 
22817971a8bfSPeter Brune   PetscFunctionBegin;
22827971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22839566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
22849566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
22859566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22869566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
22873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22887971a8bfSPeter Brune }
22897971a8bfSPeter Brune 
2290d25893d9SBarry Smith /*@C
2291dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2292d25893d9SBarry Smith 
2293c3339decSBarry Smith   Logically Collective
2294d25893d9SBarry Smith 
2295d25893d9SBarry Smith   Input Parameters:
2296f6dfbefdSBarry Smith + snes - the `SNES` context
2297d25893d9SBarry Smith . func - function evaluation routine
2298d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2299dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2300d25893d9SBarry Smith 
230120f4b53cSBarry Smith   Calling sequence of `func`:
230220f4b53cSBarry Smith $    PetscErrorCode func(SNES snes, Vec x, void *ctx);
230320f4b53cSBarry Smith + snes - the `SNES` solver
230420f4b53cSBarry Smith . x    - vector to put initial guess
2305d25893d9SBarry Smith - ctx  - optional user-defined function context
2306d25893d9SBarry Smith 
2307d25893d9SBarry Smith   Level: intermediate
2308d25893d9SBarry Smith 
23091cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`
2310d25893d9SBarry Smith @*/
23110b4db180SJacob Faibussowitsch PetscErrorCode SNESSetComputeInitialGuess(SNES snes, PetscErrorCode (*func)(SNES snes, Vec x, void *ctx), void *ctx)
2312d71ae5a4SJacob Faibussowitsch {
2313d25893d9SBarry Smith   PetscFunctionBegin;
2314d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2315d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2316d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2318d25893d9SBarry Smith }
2319d25893d9SBarry Smith 
23201096aae1SMatthew Knepley /*@C
2321dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
23221096aae1SMatthew Knepley   it assumes a zero right hand side.
23231096aae1SMatthew Knepley 
2324c3339decSBarry Smith   Logically Collective
23251096aae1SMatthew Knepley 
23261096aae1SMatthew Knepley   Input Parameter:
2327f6dfbefdSBarry Smith . snes - the `SNES` context
23281096aae1SMatthew Knepley 
23291096aae1SMatthew Knepley   Output Parameter:
2330dc4c0fb0SBarry Smith . rhs - the right hand side vector or `NULL` if the right hand side vector is null
23311096aae1SMatthew Knepley 
23321096aae1SMatthew Knepley   Level: intermediate
23331096aae1SMatthew Knepley 
23341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23351096aae1SMatthew Knepley @*/
2336d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2337d71ae5a4SJacob Faibussowitsch {
23381096aae1SMatthew Knepley   PetscFunctionBegin;
23390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23404f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
234185385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23431096aae1SMatthew Knepley }
23441096aae1SMatthew Knepley 
23459b94acceSBarry Smith /*@
2346f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23479b94acceSBarry Smith 
2348c3339decSBarry Smith   Collective
2349c7afd0dbSLois Curfman McInnes 
23509b94acceSBarry Smith   Input Parameters:
2351f6dfbefdSBarry Smith + snes - the `SNES` context
2352c7afd0dbSLois Curfman McInnes - x    - input vector
23539b94acceSBarry Smith 
23549b94acceSBarry Smith   Output Parameter:
2355f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
23569b94acceSBarry Smith 
2357dc4c0fb0SBarry Smith   Level: developer
2358dc4c0fb0SBarry Smith 
2359f6dfbefdSBarry Smith   Note:
2360f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2361bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
236236851e7fSLois Curfman McInnes 
23631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
23649b94acceSBarry Smith @*/
2365d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2366d71ae5a4SJacob Faibussowitsch {
23676cab3a1bSJed Brown   DM     dm;
2368942e3340SBarry Smith   DMSNES sdm;
23699b94acceSBarry Smith 
23703a40ed3dSBarry Smith   PetscFunctionBegin;
23710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23720700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
23730700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2374c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2375c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2376e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2377184914b5SBarry Smith 
23789566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23799566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
23800fdf79fbSJacob 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().");
238132f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
238248a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
23839566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
23848ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
23858ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2386800f99ffSJeremy L Thompson     {
2387800f99ffSJeremy L Thompson       void *ctx;
2388800f99ffSJeremy L Thompson       PetscErrorCode (*computefunction)(SNES, Vec, Vec, void *);
2389800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2390800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2391800f99ffSJeremy L Thompson     }
23929566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
239348a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
23940fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
23959566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
23960fdf79fbSJacob Faibussowitsch   }
23971baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2398ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2399422a814eSBarry Smith   /*
2400422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2401422a814eSBarry Smith      propagate the value to all processes
2402422a814eSBarry Smith   */
24031baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24059b94acceSBarry Smith }
24069b94acceSBarry Smith 
2407c79ef259SPeter Brune /*@
2408f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2409bbc1464cSBarry Smith 
2410c3339decSBarry Smith   Collective
2411bbc1464cSBarry Smith 
2412bbc1464cSBarry Smith   Input Parameters:
2413f6dfbefdSBarry Smith + snes - the `SNES` context
2414bbc1464cSBarry Smith - x    - input vector
2415bbc1464cSBarry Smith 
2416bbc1464cSBarry Smith   Output Parameter:
2417f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2418bbc1464cSBarry Smith 
2419dc4c0fb0SBarry Smith   Level: developer
2420dc4c0fb0SBarry Smith 
2421bbc1464cSBarry Smith   Notes:
2422f6dfbefdSBarry Smith   `SNESComputeMFFunction()` is used within the matrix vector products called by the matrix created with `MatCreateSNESMF()`
2423bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2424bbc1464cSBarry Smith 
2425f6dfbefdSBarry Smith   Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with `SNESSolve()`
2426f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2427f6dfbefdSBarry Smith   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.
2428bbc1464cSBarry Smith 
24291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2430bbc1464cSBarry Smith @*/
2431d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2432d71ae5a4SJacob Faibussowitsch {
2433bbc1464cSBarry Smith   DM     dm;
2434bbc1464cSBarry Smith   DMSNES sdm;
2435bbc1464cSBarry Smith 
2436bbc1464cSBarry Smith   PetscFunctionBegin;
2437bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2438bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2439bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2440bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2441bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2442e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2443bbc1464cSBarry Smith 
24449566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24459566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24479566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2448bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2449bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2450792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24519566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2453bbc1464cSBarry Smith   snes->nfuncs++;
2454bbc1464cSBarry Smith   /*
2455bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2456bbc1464cSBarry Smith      propagate the value to all processes
2457bbc1464cSBarry Smith   */
24581baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2460bbc1464cSBarry Smith }
2461bbc1464cSBarry Smith 
2462bbc1464cSBarry Smith /*@
2463f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with  `SNESSetNGS()`.
2464c79ef259SPeter Brune 
2465c3339decSBarry Smith   Collective
2466c79ef259SPeter Brune 
2467c79ef259SPeter Brune   Input Parameters:
2468f6dfbefdSBarry Smith + snes - the `SNES` context
2469c79ef259SPeter Brune . x    - input vector
2470c79ef259SPeter Brune - b    - rhs vector
2471c79ef259SPeter Brune 
2472c79ef259SPeter Brune   Output Parameter:
2473c79ef259SPeter Brune . x - new solution vector
2474c79ef259SPeter Brune 
2475dc4c0fb0SBarry Smith   Level: developer
2476dc4c0fb0SBarry Smith 
2477f6dfbefdSBarry Smith   Note:
2478f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2479c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2480c79ef259SPeter Brune   themselves.
2481c79ef259SPeter Brune 
24821cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESSetNGS()`, `SNESComputeFunction()`
2483c79ef259SPeter Brune @*/
2484d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2485d71ae5a4SJacob Faibussowitsch {
24866cab3a1bSJed Brown   DM     dm;
2487942e3340SBarry Smith   DMSNES sdm;
2488646217ecSPeter Brune 
2489646217ecSPeter Brune   PetscFunctionBegin;
2490646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2491064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2492064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2493064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2494064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2495e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
24969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
24979566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24989566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24990fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25009566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2501792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25029566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2505646217ecSPeter Brune }
2506646217ecSPeter Brune 
2507d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2508d71ae5a4SJacob Faibussowitsch {
250912837594SBarry Smith   Mat               A, B, C, D, jacobian;
2510e885f1abSBarry Smith   Vec               x = snes->vec_sol, f = snes->vec_func;
2511e885f1abSBarry Smith   PetscReal         nrm, gnorm;
251281e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
25130e276705SLisandro Dalcin   MatType           mattype;
2514e885f1abSBarry Smith   PetscInt          m, n, M, N;
2515e885f1abSBarry Smith   void             *functx;
25162cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
25173325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2518e885f1abSBarry Smith   MPI_Comm          comm;
2519e885f1abSBarry Smith   PetscInt          tabs;
252012837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
25213325ff46SBarry Smith   PetscViewerFormat format;
2522e885f1abSBarry Smith 
2523e885f1abSBarry Smith   PetscFunctionBegin;
2524d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
25259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
25269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
25279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
25284ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
25299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
25304ead3382SBarry Smith   /* Cannot remove the what otherwise would be redundant call to (PetscOptionsReal("-snes_test_jacobian_display_threshold") below because its usage is different than the replacement usage */
25319566063dSJacob 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));
2532d0609cedSBarry Smith   PetscOptionsEnd();
25333ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2534e885f1abSBarry Smith 
25359566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
25369566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
25379566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
25389566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
25399566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
254012837594SBarry Smith   if (!complete_print && !directionsprinted) {
25419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
25429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
254312837594SBarry Smith   }
254412837594SBarry Smith   if (!directionsprinted) {
25459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
25469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
254712837594SBarry Smith     directionsprinted = PETSC_TRUE;
2548e885f1abSBarry Smith   }
25491baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2550e885f1abSBarry Smith 
25519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
255212837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
255312837594SBarry Smith   else jacobian = snes->jacobian_pre;
255412837594SBarry Smith 
2555a82339d0SMatthew G. Knepley   if (!x) {
25569566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(jacobian, &x, NULL));
2557a82339d0SMatthew G. Knepley   } else {
25589566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
2559a82339d0SMatthew G. Knepley   }
2560a82339d0SMatthew G. Knepley   if (!f) {
25619566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &f));
2562a82339d0SMatthew G. Knepley   } else {
25639566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)f));
2564a82339d0SMatthew G. Knepley   }
2565a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
25669566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
25679566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
25689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
256912837594SBarry Smith   while (jacobian) {
25702cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
25712cd624f9SStefano Zampini 
25722cd624f9SStefano Zampini     if (istranspose) {
25739566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
25742cd624f9SStefano Zampini       Jsave    = jacobian;
25752cd624f9SStefano Zampini       jacobian = JT;
25762cd624f9SStefano Zampini     }
25779566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
257812837594SBarry Smith     if (flg) {
257912837594SBarry Smith       A = jacobian;
25809566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
258112837594SBarry Smith     } else {
25829566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
258312837594SBarry Smith     }
2584e885f1abSBarry Smith 
25859566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
25869566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
25879566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
25889566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
25899566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
25909566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
25919566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
25929566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
25939566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2594e885f1abSBarry Smith 
25959566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
25969566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
259712837594SBarry Smith 
25989566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
25999566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26009566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
26019566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
26029566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
260312837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
26049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
260512837594SBarry Smith 
2606e885f1abSBarry Smith     if (complete_print) {
26079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
26089566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
26099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
26109566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2611e885f1abSBarry Smith     }
2612e885f1abSBarry Smith 
2613df10fb39SFande Kong     if (threshold_print || complete_print) {
2614e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2615e885f1abSBarry Smith       PetscScalar       *cvals;
2616e885f1abSBarry Smith       const PetscInt    *bcols;
2617e885f1abSBarry Smith       const PetscScalar *bvals;
2618e885f1abSBarry Smith 
26199566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
26209566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
26219566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
26229566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
26239566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
26249566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
26250e276705SLisandro Dalcin 
26269566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26279566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2628e885f1abSBarry Smith 
2629e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
26309566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
26319566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2632e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
263323a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2634e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2635e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2636e885f1abSBarry Smith             cncols += 1;
2637e885f1abSBarry Smith           }
2638e885f1abSBarry Smith         }
263948a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
26409566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
26419566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2642e885f1abSBarry Smith       }
26439566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
26449566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
26459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
26469566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
26479566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2648e885f1abSBarry Smith     }
26499566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
26509566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
26519566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
26522cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
265312837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
265412837594SBarry Smith       jacobian = snes->jacobian_pre;
26559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
26569371c9d4SSatish Balay     } else jacobian = NULL;
265712837594SBarry Smith   }
26589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
26591baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
26609566063dSJacob Faibussowitsch   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
26619566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
26623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2663e885f1abSBarry Smith }
2664e885f1abSBarry Smith 
266562fef451SLois Curfman McInnes /*@
2666f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
266762fef451SLois Curfman McInnes 
2668c3339decSBarry Smith   Collective
2669c7afd0dbSLois Curfman McInnes 
267062fef451SLois Curfman McInnes   Input Parameters:
2671f6dfbefdSBarry Smith + snes - the `SNES` context
2672e4094ef1SJacob Faibussowitsch - X    - input vector
267362fef451SLois Curfman McInnes 
267462fef451SLois Curfman McInnes   Output Parameters:
2675c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2676f6dfbefdSBarry Smith - B - optional matrix for building the preconditioner
2677fee21e36SBarry Smith 
2678e35cf81dSBarry Smith   Options Database Keys:
267967b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
268067b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2681455a5933SJed 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.
2682455a5933SJed 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
2683693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2684693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2685693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
26864c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
268794d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2688a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2689c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2690dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2691dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2692a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2693a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2694c01495d3SJed Brown 
2695dc4c0fb0SBarry Smith   Level: developer
2696dc4c0fb0SBarry Smith 
2697f6dfbefdSBarry Smith   Note:
269862fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
269962fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
270062fef451SLois Curfman McInnes 
2701e4094ef1SJacob Faibussowitsch   Developer Notes:
2702dc4c0fb0SBarry 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
2703dc4c0fb0SBarry Smith   for with the `SNESType` of test that has been removed.
2704e885f1abSBarry Smith 
27051cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
270662fef451SLois Curfman McInnes @*/
2707d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2708d71ae5a4SJacob Faibussowitsch {
2709ace3abfcSBarry Smith   PetscBool flag;
27106cab3a1bSJed Brown   DM        dm;
2711942e3340SBarry Smith   DMSNES    sdm;
2712e0e3a89bSBarry Smith   KSP       ksp;
27133a40ed3dSBarry Smith 
27143a40ed3dSBarry Smith   PetscFunctionBegin;
27150700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
27160700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2717c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2718e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
27199566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
27209566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
27213232da50SPeter Brune 
272201c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2723fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2724fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2725f5af7f23SKarl Rupp 
27269566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2727fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
27289566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
27299566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2730ebd3b9afSBarry Smith     if (flag) {
27319566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27329566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2733ebd3b9afSBarry Smith     }
27343ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
273537ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
273663a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
27379566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2738ebd3b9afSBarry Smith     if (flag) {
27399566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27409566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2741ebd3b9afSBarry Smith     }
27423ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2743e35cf81dSBarry Smith   }
2744efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
27459566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27469566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
27473ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2748d728fb7dSPeter Brune   }
2749e35cf81dSBarry Smith 
27509566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
27519566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2752800f99ffSJeremy L Thompson   {
2753800f99ffSJeremy L Thompson     void *ctx;
2754800f99ffSJeremy L Thompson     PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *);
2755800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2756800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2757800f99ffSJeremy L Thompson   }
27589566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
27599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
276028d58a37SPierre Jolivet 
276128d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
27629566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2763a8054027SBarry Smith 
2764e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
27659566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
27663b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
27679566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
27689566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
27693b4f5425SBarry Smith     snes->lagpreconditioner = -1;
27703b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
27719566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
27729566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
277337ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
277463a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
27759566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2776d1e9a80fSBarry Smith   } else {
27779566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
27789566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2779a8054027SBarry Smith   }
2780a8054027SBarry Smith 
27819566063dSJacob Faibussowitsch   PetscCall(SNESTestJacobian(snes));
27826d84be18SBarry Smith   /* make sure user returned a correct Jacobian and preconditioner */
278394ab13aaSBarry Smith   /* PetscValidHeaderSpecific(A,MAT_CLASSID,3);
278494ab13aaSBarry Smith     PetscValidHeaderSpecific(B,MAT_CLASSID,4);   */
2785693365a8SJed Brown   {
2786693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
27879566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
27889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
27899566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
27909566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2791693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
27920298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2793693365a8SJed Brown       PetscViewer vdraw, vstdout;
27946b3a5b13SJed Brown       PetscBool   flg;
2795693365a8SJed Brown       if (flag_operator) {
27969566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2797693365a8SJed Brown         Bexp = Bexp_mine;
2798693365a8SJed Brown       } else {
2799693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
28009566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
280194ab13aaSBarry Smith         if (flg) Bexp = B;
2802693365a8SJed Brown         else {
2803693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
28049566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2805693365a8SJed Brown           Bexp = Bexp_mine;
2806693365a8SJed Brown         }
2807693365a8SJed Brown       }
28089566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
28099566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
28109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2811693365a8SJed Brown       if (flag_draw || flag_contour) {
28129566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28139566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28140298fd71SBarry Smith       } else vdraw = NULL;
28159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
28169566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
28179566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
28189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
28199566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
28209566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
28219566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
28229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
28239566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2824693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
28259566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28269566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
28279566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2828693365a8SJed Brown       }
28299566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
28309566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
28319566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
28329566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2833693365a8SJed Brown     }
2834693365a8SJed Brown   }
28354c30e9fbSJed Brown   {
28366719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
28376719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
28389566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
28399566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
28409566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
28419566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
28429566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
284327b0f280SBarry Smith     if (flag_threshold) {
28449566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
28459566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
284627b0f280SBarry Smith     }
28476719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
28484c30e9fbSJed Brown       Mat           Bfd;
28494c30e9fbSJed Brown       PetscViewer   vdraw, vstdout;
2850335efc43SPeter Brune       MatColoring   coloring;
28514c30e9fbSJed Brown       ISColoring    iscoloring;
28524c30e9fbSJed Brown       MatFDColoring matfdcoloring;
28534c30e9fbSJed Brown       PetscErrorCode (*func)(SNES, Vec, Vec, void *);
28544c30e9fbSJed Brown       void     *funcctx;
28556719d8e4SJed Brown       PetscReal norm1, norm2, normmax;
28564c30e9fbSJed Brown 
28579566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
28589566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
28599566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
28609566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
28619566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
28629566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
28639566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
28649566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28659566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
28669566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
28674c30e9fbSJed Brown 
28684c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
28699566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
28709566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
28719566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
28729566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
28739566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28749566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
28759566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
28764c30e9fbSJed Brown 
28779566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
28784c30e9fbSJed Brown       if (flag_draw || flag_contour) {
28799566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28809566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28810298fd71SBarry Smith       } else vdraw = NULL;
28829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
28839566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
28849566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
28859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
28869566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
28879566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
28889566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
28899566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
28909566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
28919566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
28929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
28939566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
28944c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
28959566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28969566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
28979566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
28984c30e9fbSJed Brown       }
28999566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29006719d8e4SJed Brown 
29016719d8e4SJed Brown       if (flag_threshold) {
29026719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
29039566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
29049566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
29056719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
29066719d8e4SJed Brown           const PetscScalar *ba, *ca;
29076719d8e4SJed Brown           const PetscInt    *bj, *cj;
29086719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
29096719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
29109566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
29119566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
29125f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
29136719d8e4SJed Brown           for (j = 0; j < bn; j++) {
29146719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
29156719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
29166719d8e4SJed Brown               maxentrycol = bj[j];
29176719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
29186719d8e4SJed Brown             }
29196719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
29206719d8e4SJed Brown               maxdiffcol = bj[j];
29216719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
29226719d8e4SJed Brown             }
29236719d8e4SJed Brown             if (rdiff > maxrdiff) {
29246719d8e4SJed Brown               maxrdiffcol = bj[j];
29256719d8e4SJed Brown               maxrdiff    = rdiff;
29266719d8e4SJed Brown             }
29276719d8e4SJed Brown           }
29286719d8e4SJed Brown           if (maxrdiff > 1) {
292963a3b9bcSJacob 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));
29306719d8e4SJed Brown             for (j = 0; j < bn; j++) {
29316719d8e4SJed Brown               PetscReal rdiff;
29326719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
293348a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
29346719d8e4SJed Brown             }
293563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
29366719d8e4SJed Brown           }
29379566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
29389566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
29396719d8e4SJed Brown         }
29406719d8e4SJed Brown       }
29419566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29429566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
29434c30e9fbSJed Brown     }
29444c30e9fbSJed Brown   }
29453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29469b94acceSBarry Smith }
29479b94acceSBarry Smith 
2948bf388a1fSBarry Smith /*MC
2949f6dfbefdSBarry Smith     SNESJacobianFunction - Function used by `SNES` to compute the nonlinear Jacobian of the function to be solved by `SNES`
2950bf388a1fSBarry Smith 
2951bf388a1fSBarry Smith      Synopsis:
2952411c0326SBarry Smith      #include "petscsnes.h"
2953411c0326SBarry Smith      PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
2954bf388a1fSBarry Smith 
2955c3339decSBarry Smith      Collective
29561843f636SBarry Smith 
29571843f636SBarry Smith     Input Parameters:
29581843f636SBarry Smith +  x - input vector, the Jacobian is to be computed at this value
2959bf388a1fSBarry Smith -  ctx - [optional] user-defined Jacobian context
2960bf388a1fSBarry Smith 
29611843f636SBarry Smith     Output Parameters:
29621843f636SBarry Smith +  Amat - the matrix that defines the (approximate) Jacobian
2963dc4c0fb0SBarry Smith -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
29641843f636SBarry Smith 
2965878cb397SSatish Balay    Level: intermediate
2966878cb397SSatish Balay 
29671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESSetJacobian()`, `SNESGetJacobian()`
2968bf388a1fSBarry Smith M*/
2969bf388a1fSBarry Smith 
29709b94acceSBarry Smith /*@C
29719b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
2972044dda88SLois Curfman McInnes   location to store the matrix.
29739b94acceSBarry Smith 
2974c3339decSBarry Smith   Logically Collective
2975c7afd0dbSLois Curfman McInnes 
29769b94acceSBarry Smith   Input Parameters:
2977f6dfbefdSBarry Smith + snes - the `SNES` context
2978e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
2979dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
2980dc4c0fb0SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFunction` for details
2981c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
2982dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
2983dc4c0fb0SBarry Smith 
2984dc4c0fb0SBarry Smith   Level: beginner
29859b94acceSBarry Smith 
29869b94acceSBarry Smith   Notes:
2987dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
298816913363SBarry Smith   each matrix.
298916913363SBarry Smith 
2990dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
2991dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
2992895c21f2SBarry Smith 
2993dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
2994f6dfbefdSBarry Smith   must be a `MatFDColoring`.
2995a8a26c1eSJed Brown 
2996c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
2997f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
2998c3cc8fd1SJed Brown 
29991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
3000db781477SPatrick Sanan           `SNESSetPicard()`, `SNESJacobianFunction`
30019b94acceSBarry Smith @*/
3002d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx)
3003d71ae5a4SJacob Faibussowitsch {
30046cab3a1bSJed Brown   DM dm;
30053a7fca6bSBarry Smith 
30063a40ed3dSBarry Smith   PetscFunctionBegin;
30070700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3008e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3009e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3010e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3011e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
30129566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30139566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3014e5d3d808SBarry Smith   if (Amat) {
30159566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
30169566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3017f5af7f23SKarl Rupp 
3018e5d3d808SBarry Smith     snes->jacobian = Amat;
30193a7fca6bSBarry Smith   }
3020e5d3d808SBarry Smith   if (Pmat) {
30219566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
30229566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3023f5af7f23SKarl Rupp 
3024e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
30253a7fca6bSBarry Smith   }
30263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30279b94acceSBarry Smith }
302862fef451SLois Curfman McInnes 
3029c2aafc4cSSatish Balay /*@C
3030b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3031b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3032b4fd4287SBarry Smith 
3033f6dfbefdSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` object is
3034c7afd0dbSLois Curfman McInnes 
3035b4fd4287SBarry Smith   Input Parameter:
3036b4fd4287SBarry Smith . snes - the nonlinear solver context
3037b4fd4287SBarry Smith 
3038b4fd4287SBarry Smith   Output Parameters:
3039dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3040dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
304120f4b53cSBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFunction`
3042dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3043fee21e36SBarry Smith 
304436851e7fSLois Curfman McInnes   Level: advanced
304536851e7fSLois Curfman McInnes 
30461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFunction`, `SNESGetFunction()`
3047b4fd4287SBarry Smith @*/
3048d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx)
3049d71ae5a4SJacob Faibussowitsch {
30506cab3a1bSJed Brown   DM dm;
30516cab3a1bSJed Brown 
30523a40ed3dSBarry Smith   PetscFunctionBegin;
30530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3054e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3055e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
30569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3057800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
30583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3059b4fd4287SBarry Smith }
3060b4fd4287SBarry Smith 
3061d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3062d71ae5a4SJacob Faibussowitsch {
306358b371f3SBarry Smith   DM     dm;
306458b371f3SBarry Smith   DMSNES sdm;
306558b371f3SBarry Smith 
306658b371f3SBarry Smith   PetscFunctionBegin;
30679566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30689566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
306958b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
307058b371f3SBarry Smith     DM        dm;
307158b371f3SBarry Smith     PetscBool isdense, ismf;
307258b371f3SBarry Smith 
30739566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
30749566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
30759566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
307658b371f3SBarry Smith     if (isdense) {
30779566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
307858b371f3SBarry Smith     } else if (!ismf) {
30799566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
308058b371f3SBarry Smith     }
308158b371f3SBarry Smith   }
30823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308358b371f3SBarry Smith }
308458b371f3SBarry Smith 
30859b94acceSBarry Smith /*@
30869b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3087272ac6f2SLois Curfman McInnes   of a nonlinear solver.
30889b94acceSBarry Smith 
3089c3339decSBarry Smith   Collective
3090fee21e36SBarry Smith 
30912fe279fdSBarry Smith   Input Parameter:
3092f6dfbefdSBarry Smith . snes - the `SNES` context
3093c7afd0dbSLois Curfman McInnes 
3094dc4c0fb0SBarry Smith   Level: advanced
3095dc4c0fb0SBarry Smith 
3096f6dfbefdSBarry Smith   Note:
3097f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3098f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3099f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3100f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3101f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3102272ac6f2SLois Curfman McInnes 
31031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
31049b94acceSBarry Smith @*/
3105d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3106d71ae5a4SJacob Faibussowitsch {
31076cab3a1bSJed Brown   DM             dm;
3108942e3340SBarry Smith   DMSNES         sdm;
3109c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
31106e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
31119b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
31129b5c1c08SStefano Zampini   Vec            f, fpc;
31139b5c1c08SStefano Zampini   void          *funcctx;
31149b5c1c08SStefano Zampini   void          *jacctx, *appctx;
31159b5c1c08SStefano Zampini   Mat            j, jpre;
31166b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
31176b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
31186e2a1849SPeter Brune   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
3119d1e9a80fSBarry Smith   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
31203a40ed3dSBarry Smith 
31213a40ed3dSBarry Smith   PetscFunctionBegin;
31220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31233ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3124fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
31259b94acceSBarry Smith 
312648a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
312785385478SLisandro Dalcin 
31289566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
312958c9b817SLisandro Dalcin 
31309566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31319566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
31329566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
313358b371f3SBarry Smith 
313448a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3135efd51863SBarry Smith 
313648a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3137b710008aSBarry Smith 
3138d8d34be6SBarry Smith   if (snes->linesearch) {
31399566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
31409566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3141d8d34be6SBarry Smith   }
31429e764e56SPeter Brune 
31439b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3144b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3145172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3146172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3147172a4300SPeter Brune   }
3148d8f46077SPeter Brune 
3149efd4aadfSBarry Smith   if (snes->npc) {
31506e2a1849SPeter Brune     /* copy the DM over */
31519566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31529566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
31536e2a1849SPeter Brune 
31549566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
31559566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
31569566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
31579566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
31589566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
31599566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
31609566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
31619b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
31629566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
31636e2a1849SPeter Brune 
31646e2a1849SPeter Brune     /* copy the function pointers over */
31659566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
31666e2a1849SPeter Brune 
31676e2a1849SPeter Brune     /* default to 1 iteration */
31689566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3169efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
31709566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3171a9936a0cSPeter Brune     } else {
31729566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3173a9936a0cSPeter Brune     }
31749566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
31756e2a1849SPeter Brune 
31766e2a1849SPeter Brune     /* copy the line search context over */
3177d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
31789566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
31799566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
31809566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
31819566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
31829566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
31839566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
31849566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
31856e2a1849SPeter Brune     }
3186d8d34be6SBarry Smith   }
31871baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
318848a46eb9SPierre Jolivet   if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user));
31896e2a1849SPeter Brune 
319037ec4e1aSPeter Brune   snes->jac_iter = 0;
319137ec4e1aSPeter Brune   snes->pre_iter = 0;
319237ec4e1aSPeter Brune 
3193dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
319458c9b817SLisandro Dalcin 
31959566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
319658b371f3SBarry Smith 
3197b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
31986c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3199d8d34be6SBarry Smith       if (snes->linesearch) {
32009566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
32019566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
32026c67d002SPeter Brune       }
32036c67d002SPeter Brune     }
3204d8d34be6SBarry Smith   }
3205fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
32067aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
32073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32089b94acceSBarry Smith }
32099b94acceSBarry Smith 
321037596af1SLisandro Dalcin /*@
3211f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
321237596af1SLisandro Dalcin 
3213c3339decSBarry Smith   Collective
321437596af1SLisandro Dalcin 
321537596af1SLisandro Dalcin   Input Parameter:
3216f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
321737596af1SLisandro Dalcin 
3218d25893d9SBarry Smith   Level: intermediate
3219d25893d9SBarry Smith 
322095452b02SPatrick Sanan   Notes:
3221f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
322237596af1SLisandro Dalcin 
3223f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3224f6dfbefdSBarry Smith 
32251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
322637596af1SLisandro Dalcin @*/
3227d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3228d71ae5a4SJacob Faibussowitsch {
322937596af1SLisandro Dalcin   PetscFunctionBegin;
323037596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3231d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
32329566063dSJacob Faibussowitsch     PetscCall((*snes->ops->userdestroy)((void **)&snes->user));
32330298fd71SBarry Smith     snes->user = NULL;
3234d25893d9SBarry Smith   }
32351baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
32368a23116dSBarry Smith 
3237dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
32381baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
32399e764e56SPeter Brune 
32401baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
32419e764e56SPeter Brune 
32429566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
32439566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
32449566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
32459566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
32469566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
32479566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
32489566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
32499566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
32509566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3251f5af7f23SKarl Rupp 
325240fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
325340fdac6aSLawrence Mitchell 
325437596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
325537596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
32563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
325737596af1SLisandro Dalcin }
325837596af1SLisandro Dalcin 
325952baeb72SSatish Balay /*@
3260f6dfbefdSBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object.
3261c4421ceaSFande Kong 
3262c3339decSBarry Smith   Collective
3263c4421ceaSFande Kong 
3264c4421ceaSFande Kong   Input Parameter:
3265f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3266c4421ceaSFande Kong 
3267c4421ceaSFande Kong   Level: intermediate
3268c4421ceaSFande Kong 
32691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`
3270c4421ceaSFande Kong @*/
3271d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3272d71ae5a4SJacob Faibussowitsch {
3273c4421ceaSFande Kong   PetscInt i;
3274c4421ceaSFande Kong 
3275c4421ceaSFande Kong   PetscFunctionBegin;
3276c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3277c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
327848a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3279c4421ceaSFande Kong   }
3280c4421ceaSFande Kong   snes->numberreasonviews = 0;
32813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3282c4421ceaSFande Kong }
3283c4421ceaSFande Kong 
32841fb7b255SJunchao Zhang /*@C
32859b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3286f6dfbefdSBarry Smith   with `SNESCreate()`.
32879b94acceSBarry Smith 
3288c3339decSBarry Smith   Collective
3289c7afd0dbSLois Curfman McInnes 
32909b94acceSBarry Smith   Input Parameter:
3291f6dfbefdSBarry Smith . snes - the `SNES` context
32929b94acceSBarry Smith 
329336851e7fSLois Curfman McInnes   Level: beginner
329436851e7fSLois Curfman McInnes 
32951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
32969b94acceSBarry Smith @*/
3297d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3298d71ae5a4SJacob Faibussowitsch {
32993a40ed3dSBarry Smith   PetscFunctionBegin;
33003ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
33016bf464f9SBarry Smith   PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1);
33029371c9d4SSatish Balay   if (--((PetscObject)(*snes))->refct > 0) {
33039371c9d4SSatish Balay     *snes = NULL;
33043ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
33059371c9d4SSatish Balay   }
3306d4bb536fSBarry Smith 
33079566063dSJacob Faibussowitsch   PetscCall(SNESReset((*snes)));
33089566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
33096b8b9a38SLisandro Dalcin 
3310e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
33119566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3312dbbe0bcdSBarry Smith   PetscTryTypeMethod((*snes), destroy);
33136d4c513bSLisandro Dalcin 
33149566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
33159566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
33169566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
33179566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
33186b8b9a38SLisandro Dalcin 
33199566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
332048a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
332148a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
33229566063dSJacob Faibussowitsch   PetscCall(SNESMonitorCancel((*snes)));
33239566063dSJacob Faibussowitsch   PetscCall(SNESConvergedReasonViewCancel((*snes)));
33249566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
33253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33269b94acceSBarry Smith }
33279b94acceSBarry Smith 
33289b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
33299b94acceSBarry Smith 
3330a8054027SBarry Smith /*@
3331a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3332a8054027SBarry Smith 
3333c3339decSBarry Smith   Logically Collective
3334a8054027SBarry Smith 
3335a8054027SBarry Smith   Input Parameters:
3336f6dfbefdSBarry Smith + snes - the `SNES` context
3337d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
33383b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3339a8054027SBarry Smith 
3340a8054027SBarry Smith   Options Database Keys:
334179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
33423d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
334379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
33443d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3345a8054027SBarry Smith 
3346a8054027SBarry Smith   Notes:
3347e4094ef1SJacob Faibussowitsch 
3348dc4c0fb0SBarry Smith   Level: intermediate
3349dc4c0fb0SBarry Smith 
3350a8054027SBarry Smith    The default is 1
3351f6dfbefdSBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3352d8e291bfSBarry Smith 
3353f6dfbefdSBarry Smith    `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3354a8054027SBarry Smith 
33551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3356f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3357a8054027SBarry Smith @*/
3358d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3359d71ae5a4SJacob Faibussowitsch {
3360a8054027SBarry Smith   PetscFunctionBegin;
33610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33625f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
33635f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3364c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3365a8054027SBarry Smith   snes->lagpreconditioner = lag;
33663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3367a8054027SBarry Smith }
3368a8054027SBarry Smith 
3369efd51863SBarry Smith /*@
3370f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3371efd51863SBarry Smith 
3372c3339decSBarry Smith   Logically Collective
3373efd51863SBarry Smith 
3374efd51863SBarry Smith   Input Parameters:
3375f6dfbefdSBarry Smith + snes  - the `SNES` context
3376efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3377efd51863SBarry Smith 
3378f6dfbefdSBarry Smith   Options Database Key:
337967b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3380efd51863SBarry Smith 
3381efd51863SBarry Smith   Level: intermediate
3382efd51863SBarry Smith 
3383f6dfbefdSBarry Smith   Note:
3384f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3385c0df2a02SJed Brown 
33861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`
3387efd51863SBarry Smith @*/
3388d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3389d71ae5a4SJacob Faibussowitsch {
3390efd51863SBarry Smith   PetscFunctionBegin;
3391efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3392efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3393efd51863SBarry Smith   snes->gridsequence = steps;
33943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3395efd51863SBarry Smith }
3396efd51863SBarry Smith 
3397fa19ca70SBarry Smith /*@
3398f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3399fa19ca70SBarry Smith 
3400c3339decSBarry Smith   Logically Collective
3401fa19ca70SBarry Smith 
3402fa19ca70SBarry Smith   Input Parameter:
3403f6dfbefdSBarry Smith . snes - the `SNES` context
3404fa19ca70SBarry Smith 
3405fa19ca70SBarry Smith   Output Parameter:
3406fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3407fa19ca70SBarry Smith 
3408f6dfbefdSBarry Smith   Options Database Key:
340967b8a455SSatish Balay . -snes_grid_sequence <steps> - set number of refinements
3410fa19ca70SBarry Smith 
3411fa19ca70SBarry Smith   Level: intermediate
3412fa19ca70SBarry Smith 
3413f6dfbefdSBarry Smith   Note:
3414f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3415fa19ca70SBarry Smith 
34161cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3417fa19ca70SBarry Smith @*/
3418d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3419d71ae5a4SJacob Faibussowitsch {
3420fa19ca70SBarry Smith   PetscFunctionBegin;
3421fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3422fa19ca70SBarry Smith   *steps = snes->gridsequence;
34233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3424fa19ca70SBarry Smith }
3425fa19ca70SBarry Smith 
3426a8054027SBarry Smith /*@
3427f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3428a8054027SBarry Smith 
34293f9fe445SBarry Smith   Not Collective
3430a8054027SBarry Smith 
3431a8054027SBarry Smith   Input Parameter:
3432f6dfbefdSBarry Smith . snes - the `SNES` context
3433a8054027SBarry Smith 
3434a8054027SBarry Smith   Output Parameter:
3435a8054027SBarry 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
34363b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3437a8054027SBarry Smith 
3438a8054027SBarry Smith   Options Database Keys:
343979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
34403d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
344179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
34423d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3443a8054027SBarry Smith 
3444dc4c0fb0SBarry Smith   Level: intermediate
3445dc4c0fb0SBarry Smith 
3446a8054027SBarry Smith   Notes:
3447a8054027SBarry Smith   The default is 1
3448f6dfbefdSBarry Smith 
3449a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3450a8054027SBarry Smith 
34511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3452a8054027SBarry Smith @*/
3453d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3454d71ae5a4SJacob Faibussowitsch {
3455a8054027SBarry Smith   PetscFunctionBegin;
34560700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3457a8054027SBarry Smith   *lag = snes->lagpreconditioner;
34583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3459a8054027SBarry Smith }
3460a8054027SBarry Smith 
3461e35cf81dSBarry Smith /*@
3462f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3463e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3464e35cf81dSBarry Smith 
3465c3339decSBarry Smith   Logically Collective
3466e35cf81dSBarry Smith 
3467e35cf81dSBarry Smith   Input Parameters:
3468f6dfbefdSBarry Smith + snes - the `SNES` context
3469e35cf81dSBarry 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
3470fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3471e35cf81dSBarry Smith 
3472e35cf81dSBarry Smith   Options Database Keys:
347379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
34743d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
347579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
34763d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3477e35cf81dSBarry Smith 
3478dc4c0fb0SBarry Smith   Level: intermediate
3479dc4c0fb0SBarry Smith 
3480e35cf81dSBarry Smith   Notes:
3481e35cf81dSBarry Smith   The default is 1
3482f6dfbefdSBarry Smith 
3483e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3484f6dfbefdSBarry Smith 
3485fe3ffe1eSBarry 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
3486fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3487e35cf81dSBarry Smith 
34881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3489e35cf81dSBarry Smith @*/
3490d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3491d71ae5a4SJacob Faibussowitsch {
3492e35cf81dSBarry Smith   PetscFunctionBegin;
34930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34945f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
34955f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3496c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3497e35cf81dSBarry Smith   snes->lagjacobian = lag;
34983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3499e35cf81dSBarry Smith }
3500e35cf81dSBarry Smith 
3501e35cf81dSBarry Smith /*@
3502f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3503e35cf81dSBarry Smith 
35043f9fe445SBarry Smith   Not Collective
3505e35cf81dSBarry Smith 
3506e35cf81dSBarry Smith   Input Parameter:
3507f6dfbefdSBarry Smith . snes - the `SNES` context
3508e35cf81dSBarry Smith 
3509e35cf81dSBarry Smith   Output Parameter:
3510e35cf81dSBarry 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
3511e35cf81dSBarry Smith          the Jacobian is built etc.
3512e35cf81dSBarry Smith 
3513dc4c0fb0SBarry Smith   Level: intermediate
3514dc4c0fb0SBarry Smith 
3515e35cf81dSBarry Smith   Notes:
3516e35cf81dSBarry Smith   The default is 1
3517f6dfbefdSBarry Smith 
3518f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3519e35cf81dSBarry Smith 
35201cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3521e35cf81dSBarry Smith 
3522e35cf81dSBarry Smith @*/
3523d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3524d71ae5a4SJacob Faibussowitsch {
3525e35cf81dSBarry Smith   PetscFunctionBegin;
35260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3527e35cf81dSBarry Smith   *lag = snes->lagjacobian;
35283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3529e35cf81dSBarry Smith }
3530e35cf81dSBarry Smith 
353137ec4e1aSPeter Brune /*@
3532f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
353337ec4e1aSPeter Brune 
3534c3339decSBarry Smith   Logically collective
353537ec4e1aSPeter Brune 
3536d8d19677SJose E. Roman   Input Parameters:
3537f6dfbefdSBarry Smith + snes - the `SNES` context
35389d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
353937ec4e1aSPeter Brune 
354037ec4e1aSPeter Brune   Options Database Keys:
354179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35423d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
354379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35443d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
35453d5a8a6aSBarry Smith 
3546dc4c0fb0SBarry Smith   Level: advanced
3547dc4c0fb0SBarry Smith 
354895452b02SPatrick Sanan   Notes:
3549f6dfbefdSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3550f6dfbefdSBarry Smith 
355195452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
355237ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
355337ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
355437ec4e1aSPeter Brune 
355542747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
355637ec4e1aSPeter Brune @*/
3557d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3558d71ae5a4SJacob Faibussowitsch {
355937ec4e1aSPeter Brune   PetscFunctionBegin;
356037ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
356137ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
356237ec4e1aSPeter Brune   snes->lagjac_persist = flg;
35633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
356437ec4e1aSPeter Brune }
356537ec4e1aSPeter Brune 
356637ec4e1aSPeter Brune /*@
3567d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
356837ec4e1aSPeter Brune 
3569c3339decSBarry Smith   Logically Collective
357037ec4e1aSPeter Brune 
3571d8d19677SJose E. Roman   Input Parameters:
3572f6dfbefdSBarry Smith + snes - the `SNES` context
35739d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
357437ec4e1aSPeter Brune 
357537ec4e1aSPeter Brune   Options Database Keys:
357679a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35773d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
357879a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35793d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
358037ec4e1aSPeter Brune 
3581dc4c0fb0SBarry Smith   Level: developer
3582dc4c0fb0SBarry Smith 
358395452b02SPatrick Sanan   Notes:
3584f6dfbefdSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3585f6dfbefdSBarry Smith 
358695452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
358737ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
358837ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
358937ec4e1aSPeter Brune 
35901cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
359137ec4e1aSPeter Brune @*/
3592d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3593d71ae5a4SJacob Faibussowitsch {
359437ec4e1aSPeter Brune   PetscFunctionBegin;
359537ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
359637ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
359737ec4e1aSPeter Brune   snes->lagpre_persist = flg;
35983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
359937ec4e1aSPeter Brune }
360037ec4e1aSPeter Brune 
36019b94acceSBarry Smith /*@
3602f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3603be5caee7SBarry Smith 
3604c3339decSBarry Smith   Logically Collective
3605be5caee7SBarry Smith 
3606be5caee7SBarry Smith   Input Parameters:
3607f6dfbefdSBarry Smith + snes  - the `SNES` context
3608f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3609be5caee7SBarry Smith 
3610f6dfbefdSBarry Smith   Options Database Key:
3611be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3612be5caee7SBarry Smith 
3613dc4c0fb0SBarry Smith   Level: intermediate
3614dc4c0fb0SBarry Smith 
3615f6dfbefdSBarry Smith   Note:
3616f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3617be5caee7SBarry Smith 
36181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3619be5caee7SBarry Smith @*/
3620d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3621d71ae5a4SJacob Faibussowitsch {
3622be5caee7SBarry Smith   PetscFunctionBegin;
3623be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3624be5caee7SBarry Smith   snes->forceiteration = force;
36253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3626be5caee7SBarry Smith }
3627be5caee7SBarry Smith 
362885216dc7SFande Kong /*@
3629f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
363085216dc7SFande Kong 
3631c3339decSBarry Smith   Logically Collective
363285216dc7SFande Kong 
36332fe279fdSBarry Smith   Input Parameter:
3634f6dfbefdSBarry Smith . snes - the `SNES` context
363585216dc7SFande Kong 
363685216dc7SFande Kong   Output Parameter:
3637dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
363885216dc7SFande Kong 
363906dd6b0eSSatish Balay   Level: intermediate
364006dd6b0eSSatish Balay 
36411cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
364285216dc7SFande Kong @*/
3643d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3644d71ae5a4SJacob Faibussowitsch {
364585216dc7SFande Kong   PetscFunctionBegin;
364685216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
364785216dc7SFande Kong   *force = snes->forceiteration;
36483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
364985216dc7SFande Kong }
3650be5caee7SBarry Smith 
3651be5caee7SBarry Smith /*@
3652f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
36539b94acceSBarry Smith 
3654c3339decSBarry Smith   Logically Collective
3655c7afd0dbSLois Curfman McInnes 
36569b94acceSBarry Smith   Input Parameters:
3657f6dfbefdSBarry Smith + snes   - the `SNES` context
365870441072SBarry Smith . abstol - absolute convergence tolerance
365933174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
36605358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3661f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
3662f6dfbefdSBarry Smith - maxf   - maximum number of function evaluations (-1 indicates no limit), default 1000
3663fee21e36SBarry Smith 
366433174efeSLois Curfman McInnes   Options Database Keys:
366570441072SBarry Smith + -snes_atol <abstol>    - Sets abstol
3666c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol>      - Sets rtol
3667c7afd0dbSLois Curfman McInnes . -snes_stol <stol>      - Sets stol
3668c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit>   - Sets maxit
3669c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf
36709b94acceSBarry Smith 
367136851e7fSLois Curfman McInnes   Level: intermediate
367236851e7fSLois Curfman McInnes 
36731cc06b55SBarry Smith .seealso: [](ch_snes), `SNESolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
36749b94acceSBarry Smith @*/
3675d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3676d71ae5a4SJacob Faibussowitsch {
36773a40ed3dSBarry Smith   PetscFunctionBegin;
36780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3679c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3680c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3681c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3682c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3683c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3684c5eb9154SBarry Smith 
368513bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
36865f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3687ab54825eSJed Brown     snes->abstol = abstol;
3688ab54825eSJed Brown   }
368913bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
36905f80ce2aSJacob 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);
3691ab54825eSJed Brown     snes->rtol = rtol;
3692ab54825eSJed Brown   }
369313bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
36945f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3695c60f73f4SPeter Brune     snes->stol = stol;
3696ab54825eSJed Brown   }
3697ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
369863a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3699ab54825eSJed Brown     snes->max_its = maxit;
3700ab54825eSJed Brown   }
3701ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
370263a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3703ab54825eSJed Brown     snes->max_funcs = maxf;
3704ab54825eSJed Brown   }
370588976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
37063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37079b94acceSBarry Smith }
37089b94acceSBarry Smith 
3709e4d06f11SPatrick Farrell /*@
3710f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3711e4d06f11SPatrick Farrell 
3712c3339decSBarry Smith   Logically Collective
3713e4d06f11SPatrick Farrell 
3714e4d06f11SPatrick Farrell   Input Parameters:
3715f6dfbefdSBarry Smith + snes   - the `SNES` context
3716f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3717e4d06f11SPatrick Farrell 
3718f6dfbefdSBarry Smith   Options Database Key:
3719dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3720e4d06f11SPatrick Farrell 
3721e4d06f11SPatrick Farrell   Level: intermediate
3722e4d06f11SPatrick Farrell 
37231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3724e4d06f11SPatrick Farrell @*/
3725d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3726d71ae5a4SJacob Faibussowitsch {
3727e4d06f11SPatrick Farrell   PetscFunctionBegin;
3728e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3729e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3730e4d06f11SPatrick Farrell 
373113bcc0bdSJacob Faibussowitsch   if (divtol != (PetscReal)PETSC_DEFAULT) {
3732e4d06f11SPatrick Farrell     snes->divtol = divtol;
37339371c9d4SSatish Balay   } else {
3734e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3735e4d06f11SPatrick Farrell   }
37363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3737e4d06f11SPatrick Farrell }
3738e4d06f11SPatrick Farrell 
37399b94acceSBarry Smith /*@
374033174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
374133174efeSLois Curfman McInnes 
3742c7afd0dbSLois Curfman McInnes   Not Collective
3743c7afd0dbSLois Curfman McInnes 
374433174efeSLois Curfman McInnes   Input Parameters:
3745f6dfbefdSBarry Smith + snes  - the `SNES` context
374685385478SLisandro Dalcin . atol  - absolute convergence tolerance
374733174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
374833174efeSLois Curfman McInnes . stol  - convergence tolerance in terms of the norm
374933174efeSLois Curfman McInnes            of the change in the solution between steps
375033174efeSLois Curfman McInnes . maxit - maximum number of iterations
3751c7afd0dbSLois Curfman McInnes - maxf  - maximum number of function evaluations
3752fee21e36SBarry Smith 
375336851e7fSLois Curfman McInnes   Level: intermediate
375436851e7fSLois Curfman McInnes 
3755dc4c0fb0SBarry Smith   Note:
3756dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3757dc4c0fb0SBarry Smith 
37581cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
375933174efeSLois Curfman McInnes @*/
3760d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3761d71ae5a4SJacob Faibussowitsch {
37623a40ed3dSBarry Smith   PetscFunctionBegin;
37630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
376485385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
376533174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3766c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
376733174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
376833174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
37693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377033174efeSLois Curfman McInnes }
377133174efeSLois Curfman McInnes 
3772e4d06f11SPatrick Farrell /*@
3773e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3774e4d06f11SPatrick Farrell 
3775e4d06f11SPatrick Farrell   Not Collective
3776e4d06f11SPatrick Farrell 
3777e4d06f11SPatrick Farrell   Input Parameters:
3778f6dfbefdSBarry Smith + snes   - the `SNES` context
3779e4d06f11SPatrick Farrell - divtol - divergence tolerance
3780e4d06f11SPatrick Farrell 
3781e4d06f11SPatrick Farrell   Level: intermediate
3782e4d06f11SPatrick Farrell 
37831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3784e4d06f11SPatrick Farrell @*/
3785d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3786d71ae5a4SJacob Faibussowitsch {
3787e4d06f11SPatrick Farrell   PetscFunctionBegin;
3788e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3789e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
37903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3791e4d06f11SPatrick Farrell }
3792e4d06f11SPatrick Farrell 
379333174efeSLois Curfman McInnes /*@
37949b94acceSBarry Smith   SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
37959b94acceSBarry Smith 
3796c3339decSBarry Smith   Logically Collective
3797fee21e36SBarry Smith 
3798c7afd0dbSLois Curfman McInnes   Input Parameters:
3799f6dfbefdSBarry Smith + snes - the `SNES` context
3800c7afd0dbSLois Curfman McInnes - tol  - tolerance
3801c7afd0dbSLois Curfman McInnes 
38029b94acceSBarry Smith   Options Database Key:
38034a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol
38049b94acceSBarry Smith 
380536851e7fSLois Curfman McInnes   Level: intermediate
380636851e7fSLois Curfman McInnes 
38071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
38089b94acceSBarry Smith @*/
3809d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3810d71ae5a4SJacob Faibussowitsch {
38113a40ed3dSBarry Smith   PetscFunctionBegin;
38120700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3813c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
38149b94acceSBarry Smith   snes->deltatol = tol;
38153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38169b94acceSBarry Smith }
38179b94acceSBarry Smith 
38186ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
38196ba87a44SLisandro Dalcin 
3820d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3821d71ae5a4SJacob Faibussowitsch {
3822b271bb04SBarry Smith   PetscDrawLG      lg;
3823b271bb04SBarry Smith   PetscReal        x, y, per;
3824b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3825b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3826b271bb04SBarry Smith   PetscDraw        draw;
3827b271bb04SBarry Smith 
3828459f5d12SBarry Smith   PetscFunctionBegin;
38294d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
38309566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
38319566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38329566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38339566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3834b271bb04SBarry Smith   x = (PetscReal)n;
383577b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
383694c9c6d3SKarl Rupp   else y = -15.0;
38379566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38386934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38399566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38409566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3841b271bb04SBarry Smith   }
3842b271bb04SBarry Smith 
38439566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
38449566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38459566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
3846aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
38479566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3848b271bb04SBarry Smith   x = (PetscReal)n;
3849b271bb04SBarry Smith   y = 100.0 * per;
38509566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38516934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38529566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38539566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3854b271bb04SBarry Smith   }
3855b271bb04SBarry Smith 
38569566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
38579371c9d4SSatish Balay   if (!n) {
38589371c9d4SSatish Balay     prev = rnorm;
38599371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
38609371c9d4SSatish Balay   }
38619566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38629566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3863b271bb04SBarry Smith   x = (PetscReal)n;
3864b271bb04SBarry Smith   y = (prev - rnorm) / prev;
38659566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38666934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38679566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38689566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3869b271bb04SBarry Smith   }
3870b271bb04SBarry Smith 
38719566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
38729566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38739566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38749566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3875b271bb04SBarry Smith   x = (PetscReal)n;
3876b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3877b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
38789566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3879b271bb04SBarry Smith   }
38806934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38819566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38829566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3883b271bb04SBarry Smith   }
3884b271bb04SBarry Smith   prev = rnorm;
38853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3886b271bb04SBarry Smith }
3887b271bb04SBarry Smith 
3888228d79bcSJed Brown /*@
38892d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
38902d157150SStefano Zampini 
38912d157150SStefano Zampini   Collective
38922d157150SStefano Zampini 
38932d157150SStefano Zampini   Input Parameters:
38942d157150SStefano Zampini + snes  - the `SNES` context
38952d157150SStefano Zampini . it    - current iteration
38962d157150SStefano Zampini . xnorm - 2-norm of current iterate
38972d157150SStefano Zampini . snorm - 2-norm of current step
38982d157150SStefano Zampini - fnorm - 2-norm of function
38992d157150SStefano Zampini 
39002d157150SStefano Zampini   Level: developer
39012d157150SStefano Zampini 
39022d157150SStefano Zampini   Note:
39032d157150SStefano Zampini   This routine is called by the `SNES` implementations.
39042d157150SStefano Zampini   It does not typically need to be called by the user.
39052d157150SStefano Zampini 
3906be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
39072d157150SStefano Zampini @*/
39082d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
39092d157150SStefano Zampini {
39102d157150SStefano Zampini   PetscFunctionBegin;
39112d157150SStefano Zampini   if (!snes->reason) {
39122d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
39132d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
39142d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
39152d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
39162d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
39172d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
39182d157150SStefano Zampini     }
39192d157150SStefano Zampini   }
39202d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
39212d157150SStefano Zampini }
39222d157150SStefano Zampini 
39232d157150SStefano Zampini /*@
3924228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
3925228d79bcSJed Brown 
3926c3339decSBarry Smith   Collective
3927228d79bcSJed Brown 
3928228d79bcSJed Brown   Input Parameters:
3929f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
3930228d79bcSJed Brown . iter  - iteration number
3931228d79bcSJed Brown - rnorm - relative norm of the residual
3932228d79bcSJed Brown 
3933dc4c0fb0SBarry Smith   Level: developer
3934dc4c0fb0SBarry Smith 
3935f6dfbefdSBarry Smith   Note:
3936f6dfbefdSBarry Smith   This routine is called by the `SNES` implementations.
3937228d79bcSJed Brown   It does not typically need to be called by the user.
3938228d79bcSJed Brown 
39391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
3940228d79bcSJed Brown @*/
3941d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
3942d71ae5a4SJacob Faibussowitsch {
39437a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
39447a03ce2fSLisandro Dalcin 
39457a03ce2fSLisandro Dalcin   PetscFunctionBegin;
39469566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
394748a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
39489566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
39493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39507a03ce2fSLisandro Dalcin }
39517a03ce2fSLisandro Dalcin 
39529b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
39539b94acceSBarry Smith 
3954bf388a1fSBarry Smith /*MC
3955f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
3956bf388a1fSBarry Smith 
3957bf388a1fSBarry Smith      Synopsis:
3958aaa7dc30SBarry Smith      #include <petscsnes.h>
395937fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
3960bf388a1fSBarry Smith 
3961c3339decSBarry Smith      Collective
39621843f636SBarry Smith 
39631843f636SBarry Smith     Input Parameters:
3964f6dfbefdSBarry Smith +    snes - the `SNES` context
3965bf388a1fSBarry Smith .    its - iteration number
3966bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
3967bf388a1fSBarry Smith -    mctx - [optional] monitoring context
3968bf388a1fSBarry Smith 
3969878cb397SSatish Balay    Level: advanced
3970878cb397SSatish Balay 
39711cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
3972bf388a1fSBarry Smith M*/
3973bf388a1fSBarry Smith 
39749b94acceSBarry Smith /*@C
3975a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
39769b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
39779b94acceSBarry Smith   progress.
39789b94acceSBarry Smith 
3979c3339decSBarry Smith   Logically Collective
3980fee21e36SBarry Smith 
3981c7afd0dbSLois Curfman McInnes   Input Parameters:
3982f6dfbefdSBarry Smith + snes           - the `SNES` context
398320f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
3984b8a78c4aSBarry Smith . mctx           - [optional] user-defined context for private data for the
3985dc4c0fb0SBarry Smith           monitor routine (use `NULL` if no context is desired)
3986dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
39879b94acceSBarry Smith 
39889665c990SLois Curfman McInnes   Options Database Keys:
3989f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
3990798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
3991dc4c0fb0SBarry 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
3992c7afd0dbSLois Curfman McInnes                             the options database.
39939665c990SLois Curfman McInnes 
3994dc4c0fb0SBarry Smith   Level: intermediate
3995dc4c0fb0SBarry Smith 
3996f6dfbefdSBarry Smith   Note:
39976bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
3998f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
39996bc08f3fSLois Curfman McInnes   order in which they were set.
4000639f9d9dSBarry Smith 
4001e4094ef1SJacob Faibussowitsch   Fortran Notes:
4002f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4003025f1a04SBarry Smith 
40041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
40059b94acceSBarry Smith @*/
4006d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4007d71ae5a4SJacob Faibussowitsch {
4008b90d0a6eSBarry Smith   PetscInt  i;
400978064530SBarry Smith   PetscBool identical;
4010b90d0a6eSBarry Smith 
40113a40ed3dSBarry Smith   PetscFunctionBegin;
40120700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4013b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
40149566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
40153ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4016649052a6SBarry Smith   }
40175f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
40186e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4019b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4020639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
40213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40229b94acceSBarry Smith }
40239b94acceSBarry Smith 
4024a278d85bSSatish Balay /*@
4025f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
40265cd90555SBarry Smith 
4027c3339decSBarry Smith   Logically Collective
4028c7afd0dbSLois Curfman McInnes 
40292fe279fdSBarry Smith   Input Parameter:
4030f6dfbefdSBarry Smith . snes - the `SNES` context
40315cd90555SBarry Smith 
40321a480d89SAdministrator   Options Database Key:
4033a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4034dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4035c7afd0dbSLois Curfman McInnes     set via the options database
40365cd90555SBarry Smith 
4037dc4c0fb0SBarry Smith   Level: intermediate
4038dc4c0fb0SBarry Smith 
4039f6dfbefdSBarry Smith   Note:
4040f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
40415cd90555SBarry Smith 
40421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
40435cd90555SBarry Smith @*/
4044d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4045d71ae5a4SJacob Faibussowitsch {
4046d952e501SBarry Smith   PetscInt i;
4047d952e501SBarry Smith 
40485cd90555SBarry Smith   PetscFunctionBegin;
40490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4050d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
405148a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4052d952e501SBarry Smith   }
40535cd90555SBarry Smith   snes->numbermonitors = 0;
40543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40555cd90555SBarry Smith }
40565cd90555SBarry Smith 
4057bf388a1fSBarry Smith /*MC
4058bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4059bf388a1fSBarry Smith 
4060bf388a1fSBarry Smith      Synopsis:
4061aaa7dc30SBarry Smith      #include <petscsnes.h>
406237fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4063bf388a1fSBarry Smith 
4064c3339decSBarry Smith      Collective
40651843f636SBarry Smith 
40661843f636SBarry Smith     Input Parameters:
4067f6dfbefdSBarry Smith +    snes - the `SNES` context
4068bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4069bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4070bf388a1fSBarry Smith .    gnorm - 2-norm of current step
40711843f636SBarry Smith .    f - 2-norm of function
40721843f636SBarry Smith -    cctx - [optional] convergence context
40731843f636SBarry Smith 
40741843f636SBarry Smith     Output Parameter:
40751843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4076bf388a1fSBarry Smith 
4077878cb397SSatish Balay    Level: intermediate
4078bf388a1fSBarry Smith 
40791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4080bf388a1fSBarry Smith M*/
4081bf388a1fSBarry Smith 
40829b94acceSBarry Smith /*@C
40839b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
40849b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
40859b94acceSBarry Smith 
4086c3339decSBarry Smith   Logically Collective
4087fee21e36SBarry Smith 
4088c7afd0dbSLois Curfman McInnes   Input Parameters:
4089f6dfbefdSBarry Smith + snes                        - the `SNES` context
4090e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4091dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4092dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
40939b94acceSBarry Smith 
409436851e7fSLois Curfman McInnes   Level: advanced
409536851e7fSLois Curfman McInnes 
40961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
40979b94acceSBarry Smith @*/
4098d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4099d71ae5a4SJacob Faibussowitsch {
41003a40ed3dSBarry Smith   PetscFunctionBegin;
41010700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4102e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
41031baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4104bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
41057f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
410685385478SLisandro Dalcin   snes->cnvP                  = cctx;
41073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41089b94acceSBarry Smith }
41099b94acceSBarry Smith 
411052baeb72SSatish Balay /*@
4111f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4112184914b5SBarry Smith 
4113184914b5SBarry Smith   Not Collective
4114184914b5SBarry Smith 
4115184914b5SBarry Smith   Input Parameter:
4116f6dfbefdSBarry Smith . snes - the `SNES` context
4117184914b5SBarry Smith 
4118184914b5SBarry Smith   Output Parameter:
4119f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4120184914b5SBarry Smith 
4121f6dfbefdSBarry Smith   Options Database Key:
41226a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
41236a4d7782SBarry Smith 
4124184914b5SBarry Smith   Level: intermediate
4125184914b5SBarry Smith 
4126f6dfbefdSBarry Smith   Note:
4127f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4128184914b5SBarry Smith 
41291cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4130184914b5SBarry Smith @*/
4131d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4132d71ae5a4SJacob Faibussowitsch {
4133184914b5SBarry Smith   PetscFunctionBegin;
41340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41354f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4136184914b5SBarry Smith   *reason = snes->reason;
41373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4138184914b5SBarry Smith }
4139184914b5SBarry Smith 
4140c4421ceaSFande Kong /*@C
4141f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4142c4421ceaSFande Kong 
4143c4421ceaSFande Kong   Not Collective
4144c4421ceaSFande Kong 
4145c4421ceaSFande Kong   Input Parameter:
4146f6dfbefdSBarry Smith . snes - the `SNES` context
4147c4421ceaSFande Kong 
4148c4421ceaSFande Kong   Output Parameter:
4149dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4150c4421ceaSFande Kong 
415199c90e12SSatish Balay   Level: beginner
4152c4421ceaSFande Kong 
41531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4154c4421ceaSFande Kong @*/
4155d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4156d71ae5a4SJacob Faibussowitsch {
4157c4421ceaSFande Kong   PetscFunctionBegin;
4158c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41594f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4160c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
41613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4162c4421ceaSFande Kong }
4163c4421ceaSFande Kong 
416433866048SMatthew G. Knepley /*@
4165f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
416633866048SMatthew G. Knepley 
416733866048SMatthew G. Knepley   Not Collective
416833866048SMatthew G. Knepley 
416933866048SMatthew G. Knepley   Input Parameters:
4170f6dfbefdSBarry Smith + snes   - the `SNES` context
4171f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
417233866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
417333866048SMatthew G. Knepley 
4174f6dfbefdSBarry Smith   Level: developer
4175f6dfbefdSBarry Smith 
4176e4094ef1SJacob Faibussowitsch   Developer Notes:
4177f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
417833866048SMatthew G. Knepley 
41791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
418033866048SMatthew G. Knepley @*/
4181d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4182d71ae5a4SJacob Faibussowitsch {
418333866048SMatthew G. Knepley   PetscFunctionBegin;
418433866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
418533866048SMatthew G. Knepley   snes->reason = reason;
41863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
418733866048SMatthew G. Knepley }
418833866048SMatthew G. Knepley 
4189c9005455SLois Curfman McInnes /*@
4190c9005455SLois Curfman McInnes   SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
4191c9005455SLois Curfman McInnes 
4192c3339decSBarry Smith   Logically Collective
4193fee21e36SBarry Smith 
4194c7afd0dbSLois Curfman McInnes   Input Parameters:
4195f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
41968c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4197cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4198758f92a0SBarry Smith . na    - size of a and its
4199f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4200758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4201c7afd0dbSLois Curfman McInnes 
4202dc4c0fb0SBarry Smith   Level: intermediate
4203dc4c0fb0SBarry Smith 
4204308dcc3eSBarry Smith   Notes:
4205dc4c0fb0SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4206308dcc3eSBarry Smith   default array of length 10000 is allocated.
4207308dcc3eSBarry Smith 
4208c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4209c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4210c9005455SLois Curfman McInnes   during the section of code that is being timed.
4211c9005455SLois Curfman McInnes 
42121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4213c9005455SLois Curfman McInnes @*/
4214d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4215d71ae5a4SJacob Faibussowitsch {
42163a40ed3dSBarry Smith   PetscFunctionBegin;
42170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42184f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
42194f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
42207a1ec6d4SBarry Smith   if (!a) {
4221308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
42229566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4223071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4224308dcc3eSBarry Smith   }
4225c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4226758f92a0SBarry Smith   snes->conv_hist_its   = its;
4227115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4228a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4229758f92a0SBarry Smith   snes->conv_hist_reset = reset;
42303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4231758f92a0SBarry Smith }
4232758f92a0SBarry Smith 
4233d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4234c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4235c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
423699e0435eSBarry Smith 
4237d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4238d71ae5a4SJacob Faibussowitsch {
4239308dcc3eSBarry Smith   mxArray   *mat;
4240308dcc3eSBarry Smith   PetscInt   i;
4241308dcc3eSBarry Smith   PetscReal *ar;
4242308dcc3eSBarry Smith 
4243308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4244308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4245f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
424611cc89d2SBarry Smith   return mat;
4247308dcc3eSBarry Smith }
4248308dcc3eSBarry Smith #endif
4249308dcc3eSBarry Smith 
42500c4c9dddSBarry Smith /*@C
4251758f92a0SBarry Smith   SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
4252758f92a0SBarry Smith 
42533f9fe445SBarry Smith   Not Collective
4254758f92a0SBarry Smith 
4255758f92a0SBarry Smith   Input Parameter:
4256f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4257758f92a0SBarry Smith 
4258758f92a0SBarry Smith   Output Parameters:
4259f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4260758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4261758f92a0SBarry Smith          negative if not converged) for each solve.
426220f4b53cSBarry Smith - na  - size of `a` and `its`
4263758f92a0SBarry Smith 
4264dc4c0fb0SBarry Smith   Level: intermediate
4265dc4c0fb0SBarry Smith 
426620f4b53cSBarry Smith   Note:
426720f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
426820f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
426920f4b53cSBarry Smith   during the section of code that is being timed.
427020f4b53cSBarry Smith 
4271e4094ef1SJacob Faibussowitsch   Fortran Notes:
4272758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4273dc4c0fb0SBarry Smith .vb
4274dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4275dc4c0fb0SBarry Smith .ve
4276758f92a0SBarry Smith 
42771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4278758f92a0SBarry Smith @*/
4279d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4280d71ae5a4SJacob Faibussowitsch {
4281758f92a0SBarry Smith   PetscFunctionBegin;
42820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4283758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4284758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4285115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
42863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4287c9005455SLois Curfman McInnes }
4288c9005455SLois Curfman McInnes 
4289ac226902SBarry Smith /*@C
429076b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4291eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
42927e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
429376b2cf59SMatthew Knepley 
4294c3339decSBarry Smith   Logically Collective
429576b2cf59SMatthew Knepley 
429676b2cf59SMatthew Knepley   Input Parameters:
4297a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4298a2b725a8SWilliam Gropp - func - The function
429976b2cf59SMatthew Knepley 
430020f4b53cSBarry Smith   Calling sequence of `func`:
430120f4b53cSBarry Smith $ PetscErrorCode func(SNES snes, PetscInt step);
430220f4b53cSBarry Smith + snes - the nonlinear solver context
430320f4b53cSBarry Smith - step - The current step of the iteration
430476b2cf59SMatthew Knepley 
4305fe97e370SBarry Smith   Level: advanced
4306fe97e370SBarry Smith 
43076b7fb656SBarry Smith   Note:
4308f6dfbefdSBarry 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
4309f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
4310fe97e370SBarry Smith   This is not used by most users.
431176b2cf59SMatthew Knepley 
4312aaa8cc7dSPierre 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.
43136b7fb656SBarry Smith 
4314e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4315db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
431676b2cf59SMatthew Knepley @*/
43170b4db180SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES snes, PetscInt step))
4318d71ae5a4SJacob Faibussowitsch {
431976b2cf59SMatthew Knepley   PetscFunctionBegin;
43200700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4321e7788613SBarry Smith   snes->ops->update = func;
43223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
432376b2cf59SMatthew Knepley }
432476b2cf59SMatthew Knepley 
432591f3e32bSBarry Smith /*@C
4326f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
43272a359c20SBarry Smith 
4328c3339decSBarry Smith   Collective
43292a359c20SBarry Smith 
4330e4094ef1SJacob Faibussowitsch   Input Parameters:
4331f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
43322a359c20SBarry Smith - viewer - the viewer to display the reason
43332a359c20SBarry Smith 
43342a359c20SBarry Smith   Options Database Keys:
4335ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4336ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4337eafd5ff0SAlex Lindsay 
4338f6dfbefdSBarry Smith   Note:
4339f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4340f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
43412a359c20SBarry Smith 
43422a359c20SBarry Smith   Level: beginner
43432a359c20SBarry Smith 
43441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4345f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4346f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4347db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
43482a359c20SBarry Smith @*/
4349d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4350d71ae5a4SJacob Faibussowitsch {
435175cca76cSMatthew G. Knepley   PetscViewerFormat format;
43522a359c20SBarry Smith   PetscBool         isAscii;
43532a359c20SBarry Smith 
43542a359c20SBarry Smith   PetscFunctionBegin;
435519a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
43569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
43572a359c20SBarry Smith   if (isAscii) {
43589566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
43599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
436075cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
436175cca76cSMatthew G. Knepley       DM       dm;
436275cca76cSMatthew G. Knepley       Vec      u;
436375cca76cSMatthew G. Knepley       PetscDS  prob;
436475cca76cSMatthew G. Knepley       PetscInt Nf, f;
436595cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
436695cbbfd3SMatthew G. Knepley       void    **exactCtx;
436775cca76cSMatthew G. Knepley       PetscReal error;
436875cca76cSMatthew G. Knepley 
43699566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
43709566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
43719566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
43729566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
43739566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
43749566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
43759566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
43769566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
43779566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
437863a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
437975cca76cSMatthew G. Knepley     }
4380eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
43812a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
438263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
43832a359c20SBarry Smith       } else {
438463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
43852a359c20SBarry Smith       }
4386eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
43872a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
438863a3b9bcSJacob 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));
43892a359c20SBarry Smith       } else {
439063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
43912a359c20SBarry Smith       }
43922a359c20SBarry Smith     }
43939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
43942a359c20SBarry Smith   }
43953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43962a359c20SBarry Smith }
43972a359c20SBarry Smith 
4398c4421ceaSFande Kong /*@C
4399c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4400aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4401c4421ceaSFande Kong 
4402c3339decSBarry Smith   Logically Collective
4403c4421ceaSFande Kong 
4404c4421ceaSFande Kong   Input Parameters:
4405f6dfbefdSBarry Smith + snes              - the `SNES` context
4406c4421ceaSFande Kong . f                 - the snes converged reason view function
4407c4421ceaSFande Kong . vctx              - [optional] user-defined context for private data for the
4408dc4c0fb0SBarry Smith           snes converged reason view routine (use `NULL` if no context is desired)
4409dc4c0fb0SBarry Smith - reasonviewdestroy - [optional] routine that frees reasonview context (may be `NULL`)
4410c4421ceaSFande Kong 
4411c4421ceaSFande Kong   Options Database Keys:
4412f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4413c4421ceaSFande Kong - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have
4414c4421ceaSFande Kong                             been hardwired into a code by
4415f6dfbefdSBarry Smith                             calls to `SNESConvergedReasonViewSet()`, but
4416c4421ceaSFande Kong                             does not cancel those set via
4417c4421ceaSFande Kong                             the options database.
4418c4421ceaSFande Kong 
4419dc4c0fb0SBarry Smith   Level: intermediate
4420dc4c0fb0SBarry Smith 
4421f6dfbefdSBarry Smith   Note:
4422c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4423f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4424c4421ceaSFande Kong   order in which they were set.
4425c4421ceaSFande Kong 
44261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4427c4421ceaSFande Kong @*/
4428d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES, void *), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **))
4429d71ae5a4SJacob Faibussowitsch {
4430c4421ceaSFande Kong   PetscInt  i;
4431c4421ceaSFande Kong   PetscBool identical;
4432c4421ceaSFande Kong 
4433c4421ceaSFande Kong   PetscFunctionBegin;
4434c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4435c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
44369566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
44373ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4438c4421ceaSFande Kong   }
44395f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4440c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4441c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4442c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
44433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4444c4421ceaSFande Kong }
4445c4421ceaSFande Kong 
444691f3e32bSBarry Smith /*@
4447f6dfbefdSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed.
4448c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
44492a359c20SBarry Smith 
4450c3339decSBarry Smith   Collective
44512a359c20SBarry Smith 
44522fe279fdSBarry Smith   Input Parameter:
4453f6dfbefdSBarry Smith . snes - the `SNES` object
44542a359c20SBarry Smith 
4455f6dfbefdSBarry Smith   Level: advanced
44562a359c20SBarry Smith 
44571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4458f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
44592a359c20SBarry Smith @*/
4460d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4461d71ae5a4SJacob Faibussowitsch {
44622a359c20SBarry Smith   PetscViewer       viewer;
44632a359c20SBarry Smith   PetscBool         flg;
44642a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
44652a359c20SBarry Smith   PetscViewerFormat format;
4466c4421ceaSFande Kong   PetscInt          i;
44672a359c20SBarry Smith 
44682a359c20SBarry Smith   PetscFunctionBegin;
44693ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
44702a359c20SBarry Smith   incall = PETSC_TRUE;
4471c4421ceaSFande Kong 
4472c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
447348a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4474c4421ceaSFande Kong 
4475c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
44769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
44772a359c20SBarry Smith   if (flg) {
44789566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
44799566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
44809566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
44819566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
44822a359c20SBarry Smith   }
44832a359c20SBarry Smith   incall = PETSC_FALSE;
44843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44852a359c20SBarry Smith }
44862a359c20SBarry Smith 
4487487a658cSBarry Smith /*@
4488f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
4489f6dfbefdSBarry Smith   Call `SNESSolve()` after calling `SNESCreate()` and optional routines of the form `SNESSetXXX()`.
44909b94acceSBarry Smith 
4491c3339decSBarry Smith   Collective
4492c7afd0dbSLois Curfman McInnes 
4493b2002411SLois Curfman McInnes   Input Parameters:
4494f6dfbefdSBarry Smith + snes - the `SNES` context
4495dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
449685385478SLisandro Dalcin - x    - the solution vector.
44979b94acceSBarry Smith 
4498dc4c0fb0SBarry Smith   Level: beginner
4499dc4c0fb0SBarry Smith 
4500f6dfbefdSBarry Smith   Note:
45018ddd3da0SLois Curfman McInnes   The user should initialize the vector,x, with the initial guess
4502f6dfbefdSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()`.  In particular,
45038ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4504f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
45058ddd3da0SLois Curfman McInnes 
45061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4507db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4508db781477SPatrick Sanan           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
45099b94acceSBarry Smith @*/
4510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4511d71ae5a4SJacob Faibussowitsch {
4512ace3abfcSBarry Smith   PetscBool flg;
4513efd51863SBarry Smith   PetscInt  grid;
45140298fd71SBarry Smith   Vec       xcreated = NULL;
4515caa4e7f2SJed Brown   DM        dm;
4516052efed2SBarry Smith 
45173a40ed3dSBarry Smith   PetscFunctionBegin;
45180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4519a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4520a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
45210700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
452285385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
452385385478SLisandro Dalcin 
452434b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
452506fc46c8SMatthew G. Knepley   {
452606fc46c8SMatthew G. Knepley     PetscViewer       viewer;
452706fc46c8SMatthew G. Knepley     PetscViewerFormat format;
45287c88af5aSMatthew G. Knepley     PetscInt          num;
452906fc46c8SMatthew G. Knepley     PetscBool         flg;
453006fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
453106fc46c8SMatthew G. Knepley 
453206fc46c8SMatthew G. Knepley     if (!incall) {
453334b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
45349566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
453506fc46c8SMatthew G. Knepley       if (flg) {
453606fc46c8SMatthew G. Knepley         PetscConvEst conv;
453746079b62SMatthew G. Knepley         DM           dm;
453846079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
453946079b62SMatthew G. Knepley         PetscInt     Nf;
454006fc46c8SMatthew G. Knepley 
454106fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
45429566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
45439566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
45449566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
45459566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
45469566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
45479566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
45489566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
45499566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
45509566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
45519566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
45529566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
45539566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
45549566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
45559566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
455606fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
455706fc46c8SMatthew G. Knepley       }
455834b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4559b2588ea6SMatthew G. Knepley       num = 1;
45609566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
456134b4d3a8SMatthew G. Knepley       if (flg) {
456234b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
456334b4d3a8SMatthew G. Knepley 
456434b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
45659566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
45669566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
45679566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
45689566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
45699566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
45709566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
45719566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
457234b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
457334b4d3a8SMatthew G. Knepley       }
45747c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
45757c88af5aSMatthew G. Knepley       num = 0;
45769566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
45777c88af5aSMatthew G. Knepley       if (num) {
45787c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
45797c88af5aSMatthew G. Knepley 
45807c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
45819566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
45829566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
45839566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
45849566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
45859566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
45869566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
45879566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
45887c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
45897c88af5aSMatthew G. Knepley       }
459006fc46c8SMatthew G. Knepley     }
459106fc46c8SMatthew G. Knepley   }
4592ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4593caa4e7f2SJed Brown   if (!x) {
45949566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
45959566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4596a69afd8bSBarry Smith     x = xcreated;
4597a69afd8bSBarry Smith   }
45989566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4599f05ece33SBarry Smith 
46009566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4601efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
460285385478SLisandro Dalcin     /* set solution vector */
46039566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
46049566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
460585385478SLisandro Dalcin     snes->vec_sol = x;
46069566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4607caa4e7f2SJed Brown 
4608caa4e7f2SJed Brown     /* set affine vector if provided */
46099566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
46109566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
461185385478SLisandro Dalcin     snes->vec_rhs = b;
461285385478SLisandro Dalcin 
46135f80ce2aSJacob 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");
46145f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
46155f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector");
4616aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
46179566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
46189566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
46193f149594SLisandro Dalcin 
46207eee914bSBarry Smith     if (!grid) {
462125e27a38SBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4622dd568438SSatish Balay     }
4623d25893d9SBarry Smith 
4624abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
46259371c9d4SSatish Balay     if (snes->counters_reset) {
46269371c9d4SSatish Balay       snes->nfuncs      = 0;
46279371c9d4SSatish Balay       snes->linear_its  = 0;
46289371c9d4SSatish Balay       snes->numFailures = 0;
46299371c9d4SSatish Balay     }
4630d5e45103SBarry Smith 
46312d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
46329566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4633dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
46349566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
46352d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4636422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
46373f149594SLisandro Dalcin 
463837ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
463937ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
464037ec4e1aSPeter Brune 
46419566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
46429566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4643c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
46449566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
46455968eb51SBarry Smith 
46465f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
46479c8e83a9SBarry Smith     if (snes->reason < 0) break;
4648efd51863SBarry Smith     if (grid < snes->gridsequence) {
4649efd51863SBarry Smith       DM  fine;
4650efd51863SBarry Smith       Vec xnew;
4651efd51863SBarry Smith       Mat interp;
4652efd51863SBarry Smith 
46539566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
46545f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
46559566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
46569566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
46579566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
46589566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
46599566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4660efd51863SBarry Smith       x = xnew;
4661efd51863SBarry Smith 
46629566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
46639566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
46649566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
46659566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
46669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4667efd51863SBarry Smith     }
4668efd51863SBarry Smith   }
46699566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
46709566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
46719566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
46729566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
46733f7e2da0SPeter Brune 
46749566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
46759566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
46763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46779b94acceSBarry Smith }
46789b94acceSBarry Smith 
46799b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
46809b94acceSBarry Smith 
468182bf6240SBarry Smith /*@C
46824b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
46839b94acceSBarry Smith 
4684c3339decSBarry Smith   Collective
4685fee21e36SBarry Smith 
4686c7afd0dbSLois Curfman McInnes   Input Parameters:
4687f6dfbefdSBarry Smith + snes - the `SNES` context
4688454a90a3SBarry Smith - type - a known method
4689c7afd0dbSLois Curfman McInnes 
4690c7afd0dbSLois Curfman McInnes   Options Database Key:
4691454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
469204d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4693ae12b187SLois Curfman McInnes 
4694dc4c0fb0SBarry Smith   Level: intermediate
4695dc4c0fb0SBarry Smith 
46969b94acceSBarry Smith   Notes:
4697e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4698f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4699c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
47004a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4701c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
47029b94acceSBarry Smith 
4703f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4704f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4705ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4706ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4707f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4708ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4709ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4710ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4711ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4712b0a32e0cSBarry Smith   appropriate method.
471336851e7fSLois Curfman McInnes 
4714e4094ef1SJacob Faibussowitsch   Developer Notes:
4715f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4716f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
47178f6c3df8SBarry Smith 
47181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
47199b94acceSBarry Smith @*/
4720d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4721d71ae5a4SJacob Faibussowitsch {
4722ace3abfcSBarry Smith   PetscBool match;
47235f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
47243a40ed3dSBarry Smith 
47253a40ed3dSBarry Smith   PetscFunctionBegin;
47260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47274f572ea9SToby Isaac   PetscAssertPointer(type, 2);
472882bf6240SBarry Smith 
47299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
47303ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
473192ff6ae8SBarry Smith 
47329566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
47336adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
473475396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4735dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
473675396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
47379e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
47389e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
47399e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
47409e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
47419e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
47427fe760d5SStefano Zampini 
47437fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
47449566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
47457fe760d5SStefano Zampini 
474675396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
474775396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4748f5af7f23SKarl Rupp 
47499566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
47509566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
47513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47529b94acceSBarry Smith }
47539b94acceSBarry Smith 
47549b94acceSBarry Smith /*@C
4755f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
47569b94acceSBarry Smith 
4757c7afd0dbSLois Curfman McInnes   Not Collective
4758c7afd0dbSLois Curfman McInnes 
47599b94acceSBarry Smith   Input Parameter:
47604b0e389bSBarry Smith . snes - nonlinear solver context
47619b94acceSBarry Smith 
47629b94acceSBarry Smith   Output Parameter:
4763f6dfbefdSBarry Smith . type - `SNES` method (a character string)
47649b94acceSBarry Smith 
476536851e7fSLois Curfman McInnes   Level: intermediate
476636851e7fSLois Curfman McInnes 
47671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
47689b94acceSBarry Smith @*/
4769d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4770d71ae5a4SJacob Faibussowitsch {
47713a40ed3dSBarry Smith   PetscFunctionBegin;
47720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47734f572ea9SToby Isaac   PetscAssertPointer(type, 2);
47747adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
47753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47769b94acceSBarry Smith }
47779b94acceSBarry Smith 
47783cd8a7caSMatthew G. Knepley /*@
4779f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
47803cd8a7caSMatthew G. Knepley 
4781c3339decSBarry Smith   Logically Collective
47823cd8a7caSMatthew G. Knepley 
47833cd8a7caSMatthew G. Knepley   Input Parameters:
4784f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
47853cd8a7caSMatthew G. Knepley - u    - the solution vector
47863cd8a7caSMatthew G. Knepley 
47873cd8a7caSMatthew G. Knepley   Level: beginner
47883cd8a7caSMatthew G. Knepley 
47891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
47903cd8a7caSMatthew G. Knepley @*/
4791d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4792d71ae5a4SJacob Faibussowitsch {
47933cd8a7caSMatthew G. Knepley   DM dm;
47943cd8a7caSMatthew G. Knepley 
47953cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
47963cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47973cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
47989566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
47999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
48003cd8a7caSMatthew G. Knepley 
48013cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
48023cd8a7caSMatthew G. Knepley 
48039566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
48049566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
48053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48063cd8a7caSMatthew G. Knepley }
48073cd8a7caSMatthew G. Knepley 
480852baeb72SSatish Balay /*@
48099b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
4810f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
48119b94acceSBarry Smith 
4812f6dfbefdSBarry Smith   Not Collective, but x is parallel if snes is parallel
4813c7afd0dbSLois Curfman McInnes 
48149b94acceSBarry Smith   Input Parameter:
4815f6dfbefdSBarry Smith . snes - the `SNES` context
48169b94acceSBarry Smith 
48179b94acceSBarry Smith   Output Parameter:
48189b94acceSBarry Smith . x - the solution
48199b94acceSBarry Smith 
482070e92668SMatthew Knepley   Level: intermediate
482136851e7fSLois Curfman McInnes 
48221cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
48239b94acceSBarry Smith @*/
4824d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4825d71ae5a4SJacob Faibussowitsch {
48263a40ed3dSBarry Smith   PetscFunctionBegin;
48270700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48284f572ea9SToby Isaac   PetscAssertPointer(x, 2);
482985385478SLisandro Dalcin   *x = snes->vec_sol;
48303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
483170e92668SMatthew Knepley }
483270e92668SMatthew Knepley 
483352baeb72SSatish Balay /*@
48349b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
48359b94acceSBarry Smith   stored.
48369b94acceSBarry Smith 
4837f6dfbefdSBarry Smith   Not Collective, but x is parallel if snes is parallel
4838c7afd0dbSLois Curfman McInnes 
48399b94acceSBarry Smith   Input Parameter:
4840f6dfbefdSBarry Smith . snes - the `SNES` context
48419b94acceSBarry Smith 
48429b94acceSBarry Smith   Output Parameter:
48439b94acceSBarry Smith . x - the solution update
48449b94acceSBarry Smith 
484536851e7fSLois Curfman McInnes   Level: advanced
484636851e7fSLois Curfman McInnes 
48471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
48489b94acceSBarry Smith @*/
4849d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4850d71ae5a4SJacob Faibussowitsch {
48513a40ed3dSBarry Smith   PetscFunctionBegin;
48520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48534f572ea9SToby Isaac   PetscAssertPointer(x, 2);
485485385478SLisandro Dalcin   *x = snes->vec_sol_update;
48553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48569b94acceSBarry Smith }
48579b94acceSBarry Smith 
48589b94acceSBarry Smith /*@C
4859f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
48609b94acceSBarry Smith 
4861f6dfbefdSBarry Smith   Not Collective, but r is parallel if snes is parallel. Collective if r is requested, but has not been created yet.
4862c7afd0dbSLois Curfman McInnes 
48639b94acceSBarry Smith   Input Parameter:
4864f6dfbefdSBarry Smith . snes - the `SNES` context
48659b94acceSBarry Smith 
4866d8d19677SJose E. Roman   Output Parameters:
4867dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
486820f4b53cSBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunction`
4869dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
48709b94acceSBarry Smith 
487136851e7fSLois Curfman McInnes   Level: advanced
487236851e7fSLois Curfman McInnes 
4873f6dfbefdSBarry Smith   Note:
4874dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
487504edfde5SBarry Smith 
4876e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction`
48779b94acceSBarry Smith @*/
4878d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4879d71ae5a4SJacob Faibussowitsch {
48806cab3a1bSJed Brown   DM dm;
4881a63bb30eSJed Brown 
48823a40ed3dSBarry Smith   PetscFunctionBegin;
48830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4884a63bb30eSJed Brown   if (r) {
4885a63bb30eSJed Brown     if (!snes->vec_func) {
4886a63bb30eSJed Brown       if (snes->vec_rhs) {
48879566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
4888a63bb30eSJed Brown       } else if (snes->vec_sol) {
48899566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
4890a63bb30eSJed Brown       } else if (snes->dm) {
48919566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
4892a63bb30eSJed Brown       }
4893a63bb30eSJed Brown     }
4894a63bb30eSJed Brown     *r = snes->vec_func;
4895a63bb30eSJed Brown   }
48969566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
48979566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
48983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48999b94acceSBarry Smith }
49009b94acceSBarry Smith 
4901c79ef259SPeter Brune /*@C
490237fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
4903c79ef259SPeter Brune 
4904c79ef259SPeter Brune   Input Parameter:
4905f6dfbefdSBarry Smith . snes - the `SNES` context
4906c79ef259SPeter Brune 
4907d8d19677SJose E. Roman   Output Parameters:
490837fdd005SBarry Smith + f   - the function (or `NULL`) see `SNESSetNGS()` for details
4909dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
4910c79ef259SPeter Brune 
4911c79ef259SPeter Brune   Level: advanced
4912c79ef259SPeter Brune 
49131cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`
4914c79ef259SPeter Brune @*/
4915d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4916d71ae5a4SJacob Faibussowitsch {
49176cab3a1bSJed Brown   DM dm;
49186cab3a1bSJed Brown 
4919646217ecSPeter Brune   PetscFunctionBegin;
4920646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49219566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49229566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
49233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4924646217ecSPeter Brune }
4925646217ecSPeter Brune 
49263c7409f5SSatish Balay /*@C
49273c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
4928f6dfbefdSBarry Smith   `SNES` options in the database.
49293c7409f5SSatish Balay 
4930c3339decSBarry Smith   Logically Collective
4931fee21e36SBarry Smith 
4932d8d19677SJose E. Roman   Input Parameters:
4933f6dfbefdSBarry Smith + snes   - the `SNES` context
4934c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
4935c7afd0dbSLois Curfman McInnes 
4936dc4c0fb0SBarry Smith   Level: advanced
4937dc4c0fb0SBarry Smith 
4938f6dfbefdSBarry Smith   Note:
4939a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
4940c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
4941d850072dSLois Curfman McInnes 
49421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
49433c7409f5SSatish Balay @*/
4944d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
4945d71ae5a4SJacob Faibussowitsch {
49463a40ed3dSBarry Smith   PetscFunctionBegin;
49470700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
49499566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
495035f5d045SPeter Brune   if (snes->linesearch) {
49519566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
49529566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
495335f5d045SPeter Brune   }
49549566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
49553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49563c7409f5SSatish Balay }
49573c7409f5SSatish Balay 
49583c7409f5SSatish Balay /*@C
4959f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
4960f6dfbefdSBarry Smith   `SNES` options in the database.
49613c7409f5SSatish Balay 
4962c3339decSBarry Smith   Logically Collective
4963fee21e36SBarry Smith 
4964c7afd0dbSLois Curfman McInnes   Input Parameters:
4965f6dfbefdSBarry Smith + snes   - the `SNES` context
4966c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
4967c7afd0dbSLois Curfman McInnes 
4968dc4c0fb0SBarry Smith   Level: advanced
4969dc4c0fb0SBarry Smith 
4970f6dfbefdSBarry Smith   Note:
4971a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
4972c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
4973d850072dSLois Curfman McInnes 
49741cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
49753c7409f5SSatish Balay @*/
4976d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
4977d71ae5a4SJacob Faibussowitsch {
49783a40ed3dSBarry Smith   PetscFunctionBegin;
49790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49809566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
49819566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
498235f5d045SPeter Brune   if (snes->linesearch) {
49839566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
49849566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
498535f5d045SPeter Brune   }
49869566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
49873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49883c7409f5SSatish Balay }
49893c7409f5SSatish Balay 
49909ab63eb5SSatish Balay /*@C
4991f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
4992f6dfbefdSBarry Smith   `SNES` options in the database.
49933c7409f5SSatish Balay 
4994c7afd0dbSLois Curfman McInnes   Not Collective
4995c7afd0dbSLois Curfman McInnes 
49963c7409f5SSatish Balay   Input Parameter:
4997f6dfbefdSBarry Smith . snes - the `SNES` context
49983c7409f5SSatish Balay 
49993c7409f5SSatish Balay   Output Parameter:
50003c7409f5SSatish Balay . prefix - pointer to the prefix string used
50013c7409f5SSatish Balay 
500236851e7fSLois Curfman McInnes   Level: advanced
500336851e7fSLois Curfman McInnes 
5004e4094ef1SJacob Faibussowitsch   Fortran Notes:
5005dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5006dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5007dc4c0fb0SBarry Smith 
50081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
50093c7409f5SSatish Balay @*/
5010d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5011d71ae5a4SJacob Faibussowitsch {
50123a40ed3dSBarry Smith   PetscFunctionBegin;
50130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50149566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
50153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50163c7409f5SSatish Balay }
50173c7409f5SSatish Balay 
50183cea93caSBarry Smith /*@C
50191c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
50201c84c290SBarry Smith 
502120f4b53cSBarry Smith   Not Collective
50221c84c290SBarry Smith 
50231c84c290SBarry Smith   Input Parameters:
502420f4b53cSBarry Smith + sname    - name of a new user-defined solver
502520f4b53cSBarry Smith - function - routine to create method context
50261c84c290SBarry Smith 
5027dc4c0fb0SBarry Smith   Level: advanced
5028dc4c0fb0SBarry Smith 
5029f6dfbefdSBarry Smith   Note:
5030f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
50311c84c290SBarry Smith 
5032e4094ef1SJacob Faibussowitsch   Example Usage:
50331c84c290SBarry Smith .vb
5034bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
50351c84c290SBarry Smith .ve
50361c84c290SBarry Smith 
50371c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
50381c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
50391c84c290SBarry Smith   or at runtime via the option
50401c84c290SBarry Smith $     -snes_type my_solver
50411c84c290SBarry Smith 
50421cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
50433cea93caSBarry Smith @*/
5044d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5045d71ae5a4SJacob Faibussowitsch {
5046b2002411SLois Curfman McInnes   PetscFunctionBegin;
50479566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
50489566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
50493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5050b2002411SLois Curfman McInnes }
5051da9b6338SBarry Smith 
5052d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5053d71ae5a4SJacob Faibussowitsch {
505477431f27SBarry Smith   PetscInt    N, i, j;
5055da9b6338SBarry Smith   Vec         u, uh, fh;
5056da9b6338SBarry Smith   PetscScalar value;
5057da9b6338SBarry Smith   PetscReal   norm;
5058da9b6338SBarry Smith 
5059da9b6338SBarry Smith   PetscFunctionBegin;
50609566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
50619566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
50629566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5063da9b6338SBarry Smith 
5064da9b6338SBarry Smith   /* currently only works for sequential */
50659566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
50669566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5067da9b6338SBarry Smith   for (i = 0; i < N; i++) {
50689566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
506963a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5070da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
50718b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
50729566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
50739566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
50749566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
507563a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5076da9b6338SBarry Smith       value = -value;
50779566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5078da9b6338SBarry Smith     }
5079da9b6338SBarry Smith   }
50809566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
50819566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
50823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5083da9b6338SBarry Smith }
508471f87433Sdalcinl 
508571f87433Sdalcinl /*@
5086f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
508771f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
508871f87433Sdalcinl   Newton method.
508971f87433Sdalcinl 
5090c3339decSBarry Smith   Logically Collective
509171f87433Sdalcinl 
509271f87433Sdalcinl   Input Parameters:
5093f6dfbefdSBarry Smith + snes - `SNES` context
5094f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
509571f87433Sdalcinl 
5096f6dfbefdSBarry Smith   Options Database Keys:
509764ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
509864ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
509964ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
510064ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
510164ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
510264ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
510364ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
510464ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
510564ba62caSBarry Smith 
5106dc4c0fb0SBarry Smith   Level: advanced
5107dc4c0fb0SBarry Smith 
5108f6dfbefdSBarry Smith   Note:
5109f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
511071f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
511171f87433Sdalcinl   Eisenstat-Walker method, where the relative convergence tolerance
511271f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
511371f87433Sdalcinl   solver.
511471f87433Sdalcinl 
5115e4094ef1SJacob Faibussowitsch   References:
5116f6dfbefdSBarry Smith .  - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996.
511771f87433Sdalcinl 
51181cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
511971f87433Sdalcinl @*/
5120d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5121d71ae5a4SJacob Faibussowitsch {
512271f87433Sdalcinl   PetscFunctionBegin;
51230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5124acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
512571f87433Sdalcinl   snes->ksp_ewconv = flag;
51263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
512771f87433Sdalcinl }
512871f87433Sdalcinl 
512971f87433Sdalcinl /*@
5130f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
513171f87433Sdalcinl   for computing relative tolerance for linear solvers within an
513271f87433Sdalcinl   inexact Newton method.
513371f87433Sdalcinl 
513471f87433Sdalcinl   Not Collective
513571f87433Sdalcinl 
513671f87433Sdalcinl   Input Parameter:
5137f6dfbefdSBarry Smith . snes - `SNES` context
513871f87433Sdalcinl 
513971f87433Sdalcinl   Output Parameter:
5140f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
514171f87433Sdalcinl 
514271f87433Sdalcinl   Level: advanced
514371f87433Sdalcinl 
51441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
514571f87433Sdalcinl @*/
5146d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5147d71ae5a4SJacob Faibussowitsch {
514871f87433Sdalcinl   PetscFunctionBegin;
51490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51504f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
515171f87433Sdalcinl   *flag = snes->ksp_ewconv;
51523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515371f87433Sdalcinl }
515471f87433Sdalcinl 
515571f87433Sdalcinl /*@
5156fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
515771f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
515871f87433Sdalcinl   Newton method.
515971f87433Sdalcinl 
5160c3339decSBarry Smith   Logically Collective
516171f87433Sdalcinl 
516271f87433Sdalcinl   Input Parameters:
5163f6dfbefdSBarry Smith + snes      - `SNES` context
51640f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
516571f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
516671f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
516771f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
516871f87433Sdalcinl              (0 <= gamma2 <= 1)
516971f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
517071f87433Sdalcinl . alpha2    - power for safeguard
517171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
517271f87433Sdalcinl 
5173dc4c0fb0SBarry Smith   Level: advanced
5174dc4c0fb0SBarry Smith 
5175f6dfbefdSBarry Smith   Notes:
517671f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
517771f87433Sdalcinl 
5178f6dfbefdSBarry Smith   Use `PETSC_DEFAULT` to retain the default for any of the parameters.
517971f87433Sdalcinl 
51801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
518171f87433Sdalcinl @*/
5182d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5183d71ae5a4SJacob Faibussowitsch {
5184fa9f3622SBarry Smith   SNESKSPEW *kctx;
51855fd66863SKarl Rupp 
518671f87433Sdalcinl   PetscFunctionBegin;
51870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5188fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
51895f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5190c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5191c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5192c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5193c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5194c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5195c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5196c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
519771f87433Sdalcinl 
519871f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
519913bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
520013bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
520113bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
520213bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
520313bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
520413bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
520571f87433Sdalcinl 
52060f0abf79SStefano 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);
52070b121fc5SBarry 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);
52080b121fc5SBarry 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);
52090b121fc5SBarry 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);
52100b121fc5SBarry 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);
52110b121fc5SBarry 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);
52123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
521371f87433Sdalcinl }
521471f87433Sdalcinl 
521571f87433Sdalcinl /*@
5216fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
521771f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
521871f87433Sdalcinl   Newton method.
521971f87433Sdalcinl 
522071f87433Sdalcinl   Not Collective
522171f87433Sdalcinl 
522297bb3fdcSJose E. Roman   Input Parameter:
5223f6dfbefdSBarry Smith . snes - `SNES` context
522471f87433Sdalcinl 
522571f87433Sdalcinl   Output Parameters:
52260f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
522771f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
522871f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5229bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
523071f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
523171f87433Sdalcinl . alpha2    - power for safeguard
523271f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
523371f87433Sdalcinl 
523471f87433Sdalcinl   Level: advanced
523571f87433Sdalcinl 
52361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
523771f87433Sdalcinl @*/
5238d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5239d71ae5a4SJacob Faibussowitsch {
5240fa9f3622SBarry Smith   SNESKSPEW *kctx;
52415fd66863SKarl Rupp 
524271f87433Sdalcinl   PetscFunctionBegin;
52430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5244fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52455f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
524671f87433Sdalcinl   if (version) *version = kctx->version;
524771f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
524871f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
524971f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
525071f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
525171f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
525271f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
52533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
525471f87433Sdalcinl }
525571f87433Sdalcinl 
5256d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5257d71ae5a4SJacob Faibussowitsch {
5258fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
525971f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
526071f87433Sdalcinl 
526171f87433Sdalcinl   PetscFunctionBegin;
52623ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
526330058271SDmitry Karpeev   if (!snes->iter) {
526430058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
52659566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
52660f0abf79SStefano Zampini   } else {
52670fdf79fbSJacob 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);
526871f87433Sdalcinl     if (kctx->version == 1) {
52690f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
527085ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
527171f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
527271f87433Sdalcinl     } else if (kctx->version == 2) {
527385ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
527485ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
527571f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
527671f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
527785ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
527871f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
527985ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
528071f87433Sdalcinl       stol = PetscMax(rtol, stol);
528171f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
528271f87433Sdalcinl       /* safeguard: avoid oversolving */
528330058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
528471f87433Sdalcinl       stol = PetscMax(rtol, stol);
528571f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
52860fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
52870fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
52880f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
52890f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
52900f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
52910f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
52920f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
52930f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
52940f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
52950f0abf79SStefano Zampini 
5296a4598233SStefano 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;
52970f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
52980f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
52990f0abf79SStefano Zampini       kctx->rk_last     = rk;
53000fdf79fbSJacob Faibussowitsch     }
53010f0abf79SStefano Zampini   }
53020f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
530371f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
53049566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
530563a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
53063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
530771f87433Sdalcinl }
530871f87433Sdalcinl 
5309d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5310d71ae5a4SJacob Faibussowitsch {
5311fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
531271f87433Sdalcinl   PCSide     pcside;
531371f87433Sdalcinl   Vec        lres;
531471f87433Sdalcinl 
531571f87433Sdalcinl   PetscFunctionBegin;
53163ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
53179566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
531871dbe336SPeter Brune   kctx->norm_last = snes->norm;
53190f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
53204f00ce20SMatthew G. Knepley     PC        pc;
53210f0abf79SStefano Zampini     PetscBool getRes;
53224f00ce20SMatthew G. Knepley 
53239566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
53240f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
53250f0abf79SStefano Zampini     if (!getRes) {
53260f0abf79SStefano Zampini       KSPNormType normtype;
53270f0abf79SStefano Zampini 
53280f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
53290f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
53300f0abf79SStefano Zampini     }
53319566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
53320f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
53339566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
533471f87433Sdalcinl     } else {
533571f87433Sdalcinl       /* KSP residual is preconditioned residual */
533671f87433Sdalcinl       /* compute true linear residual norm */
53370f0abf79SStefano Zampini       Mat J;
53380f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
53399566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
53400f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
53419566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
53429566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
53439566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
534471f87433Sdalcinl     }
534571f87433Sdalcinl   }
53463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
534771f87433Sdalcinl }
534871f87433Sdalcinl 
5349d4211eb9SBarry Smith /*@
5350f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5351d4211eb9SBarry Smith 
5352f6dfbefdSBarry Smith   Not Collective, but if snes is parallel, then ksp is parallel
5353d4211eb9SBarry Smith 
5354d4211eb9SBarry Smith   Input Parameter:
5355f6dfbefdSBarry Smith . snes - the `SNES` context
5356d4211eb9SBarry Smith 
5357d4211eb9SBarry Smith   Output Parameter:
5358f6dfbefdSBarry Smith . ksp - the `KSP` context
5359d4211eb9SBarry Smith 
5360dc4c0fb0SBarry Smith   Level: beginner
5361dc4c0fb0SBarry Smith 
5362d4211eb9SBarry Smith   Notes:
5363f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5364d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5365f6dfbefdSBarry Smith   `PC` contexts as well.
5366f6dfbefdSBarry Smith 
5367f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5368d4211eb9SBarry Smith 
53691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5370d4211eb9SBarry Smith @*/
5371d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5372d71ae5a4SJacob Faibussowitsch {
537371f87433Sdalcinl   PetscFunctionBegin;
5374d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
53754f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5376d4211eb9SBarry Smith 
5377d4211eb9SBarry Smith   if (!snes->ksp) {
53789566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
53799566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5380d4211eb9SBarry Smith 
53819566063dSJacob Faibussowitsch     PetscCall(KSPSetPreSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_SNESEW, snes));
53829566063dSJacob Faibussowitsch     PetscCall(KSPSetPostSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_SNESEW, snes));
5383a5c2985bSBarry Smith 
53849566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
53859566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5386d4211eb9SBarry Smith   }
5387d4211eb9SBarry Smith   *ksp = snes->ksp;
53883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
538971f87433Sdalcinl }
53906c699258SBarry Smith 
5391af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
53926c699258SBarry Smith /*@
5393f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
53946c699258SBarry Smith 
5395c3339decSBarry Smith   Logically Collective
53966c699258SBarry Smith 
53976c699258SBarry Smith   Input Parameters:
53982a808120SBarry Smith + snes - the nonlinear solver context
5399dc4c0fb0SBarry Smith - dm   - the dm, cannot be `NULL`
5400dc4c0fb0SBarry Smith 
5401dc4c0fb0SBarry Smith   Level: intermediate
54026c699258SBarry Smith 
5403f6dfbefdSBarry Smith   Note:
5404f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5405f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5406e03a659cSJed Brown   problems using the same function space.
5407e03a659cSJed Brown 
54081cc06b55SBarry Smith .seealso: [](ch_snes), `DM`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
54096c699258SBarry Smith @*/
5410d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5411d71ae5a4SJacob Faibussowitsch {
5412345fed2cSBarry Smith   KSP    ksp;
5413942e3340SBarry Smith   DMSNES sdm;
54146c699258SBarry Smith 
54156c699258SBarry Smith   PetscFunctionBegin;
54160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54172a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
54189566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5419942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
542051f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
54219566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
54229566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5423f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
54246cab3a1bSJed Brown     }
54259566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
54269566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
54276cab3a1bSJed Brown   }
54286c699258SBarry Smith   snes->dm     = dm;
5429116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5430f5af7f23SKarl Rupp 
54319566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
54329566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
54339566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5434efd4aadfSBarry Smith   if (snes->npc) {
54359566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
54369566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
54372c155ee1SBarry Smith   }
54383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54396c699258SBarry Smith }
54406c699258SBarry Smith 
54416c699258SBarry Smith /*@
5442f6dfbefdSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some preconditioners
54436c699258SBarry Smith 
5444f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
54456c699258SBarry Smith 
54466c699258SBarry Smith   Input Parameter:
54476c699258SBarry Smith . snes - the preconditioner context
54486c699258SBarry Smith 
54496c699258SBarry Smith   Output Parameter:
54506c699258SBarry Smith . dm - the dm
54516c699258SBarry Smith 
54526c699258SBarry Smith   Level: intermediate
54536c699258SBarry Smith 
54541cc06b55SBarry Smith .seealso: [](ch_snes), `DM`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
54556c699258SBarry Smith @*/
5456d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5457d71ae5a4SJacob Faibussowitsch {
54586c699258SBarry Smith   PetscFunctionBegin;
54590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54606cab3a1bSJed Brown   if (!snes->dm) {
54619566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5462116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
54636cab3a1bSJed Brown   }
54646c699258SBarry Smith   *dm = snes->dm;
54653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54666c699258SBarry Smith }
54670807856dSBarry Smith 
546831823bd8SMatthew G Knepley /*@
5469be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
547031823bd8SMatthew G Knepley 
5471c3339decSBarry Smith   Collective
547231823bd8SMatthew G Knepley 
547331823bd8SMatthew G Knepley   Input Parameters:
5474f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5475f6dfbefdSBarry Smith - npc  - the preconditioner object
547631823bd8SMatthew G Knepley 
5477dc4c0fb0SBarry Smith   Level: developer
5478dc4c0fb0SBarry Smith 
547931823bd8SMatthew G Knepley   Notes:
5480f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
548131823bd8SMatthew G Knepley   to configure it using the API).
548231823bd8SMatthew G Knepley 
5483f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5484f6dfbefdSBarry Smith 
54851cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
548631823bd8SMatthew G Knepley @*/
5487d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5488d71ae5a4SJacob Faibussowitsch {
548931823bd8SMatthew G Knepley   PetscFunctionBegin;
549031823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5491f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5492f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5493f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
54949566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5495f6dfbefdSBarry Smith   snes->npc = npc;
54963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
549731823bd8SMatthew G Knepley }
549831823bd8SMatthew G Knepley 
549931823bd8SMatthew G Knepley /*@
5500f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
550131823bd8SMatthew G Knepley 
5502f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
550331823bd8SMatthew G Knepley 
550431823bd8SMatthew G Knepley   Input Parameter:
5505f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
550631823bd8SMatthew G Knepley 
550731823bd8SMatthew G Knepley   Output Parameter:
5508e4094ef1SJacob Faibussowitsch . pc - preconditioner context
550931823bd8SMatthew G Knepley 
5510f6dfbefdSBarry Smith   Options Database Key:
5511f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5512b5badacbSBarry Smith 
5513dc4c0fb0SBarry Smith   Level: developer
5514dc4c0fb0SBarry Smith 
551595452b02SPatrick Sanan   Notes:
5516f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5517be95d8f1SBarry Smith 
5518f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5519f6dfbefdSBarry Smith   `SNES`
5520951fe5abSBarry Smith 
55211cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
552231823bd8SMatthew G Knepley @*/
5523d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5524d71ae5a4SJacob Faibussowitsch {
5525a64e098fSPeter Brune   const char *optionsprefix;
552631823bd8SMatthew G Knepley 
552731823bd8SMatthew G Knepley   PetscFunctionBegin;
552831823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55294f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5530efd4aadfSBarry Smith   if (!snes->npc) {
5531ec785e5bSStefano Zampini     void *ctx;
5532ec785e5bSStefano Zampini 
55339566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
55349566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
55359566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
55369566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
55379566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5538ec785e5bSStefano Zampini     PetscCall(SNESGetApplicationContext(snes, &ctx));
5539ec785e5bSStefano Zampini     PetscCall(SNESSetApplicationContext(snes->npc, ctx));
55409566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
554131823bd8SMatthew G Knepley   }
5542efd4aadfSBarry Smith   *pc = snes->npc;
55433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
554431823bd8SMatthew G Knepley }
554531823bd8SMatthew G Knepley 
55463ad1a0b9SPatrick Farrell /*@
55473ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
55483ad1a0b9SPatrick Farrell 
55493ad1a0b9SPatrick Farrell   Not Collective
55503ad1a0b9SPatrick Farrell 
55513ad1a0b9SPatrick Farrell   Input Parameter:
5552f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
55533ad1a0b9SPatrick Farrell 
55543ad1a0b9SPatrick Farrell   Output Parameter:
5555f6dfbefdSBarry Smith . has_npc - whether the `SNES` has an NPC or not
55563ad1a0b9SPatrick Farrell 
55573ad1a0b9SPatrick Farrell   Level: developer
55583ad1a0b9SPatrick Farrell 
55591cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
55603ad1a0b9SPatrick Farrell @*/
5561d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5562d71ae5a4SJacob Faibussowitsch {
55633ad1a0b9SPatrick Farrell   PetscFunctionBegin;
55643ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5565efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
55663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55673ad1a0b9SPatrick Farrell }
55683ad1a0b9SPatrick Farrell 
5569c40d0f55SPeter Brune /*@
5570be95d8f1SBarry Smith   SNESSetNPCSide - Sets the preconditioning side.
5571c40d0f55SPeter Brune 
5572c3339decSBarry Smith   Logically Collective
5573c40d0f55SPeter Brune 
5574c40d0f55SPeter Brune   Input Parameter:
5575f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5576c40d0f55SPeter Brune 
5577c40d0f55SPeter Brune   Output Parameter:
5578c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5579c40d0f55SPeter Brune .vb
55802d547940SBarry Smith       PC_LEFT - left preconditioning
55812d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5582c40d0f55SPeter Brune .ve
5583c40d0f55SPeter Brune 
5584f6dfbefdSBarry Smith   Options Database Key:
558567b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5586c40d0f55SPeter Brune 
5587dc4c0fb0SBarry Smith   Level: intermediate
5588dc4c0fb0SBarry Smith 
5589f6dfbefdSBarry Smith   Note:
5590f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
55912d547940SBarry Smith 
55921cc06b55SBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`
5593c40d0f55SPeter Brune @*/
5594d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5595d71ae5a4SJacob Faibussowitsch {
5596c40d0f55SPeter Brune   PetscFunctionBegin;
5597c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5598c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5599b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
560054c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5601efd4aadfSBarry Smith   snes->npcside = side;
56023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5603c40d0f55SPeter Brune }
5604c40d0f55SPeter Brune 
5605c40d0f55SPeter Brune /*@
5606be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5607c40d0f55SPeter Brune 
5608c40d0f55SPeter Brune   Not Collective
5609c40d0f55SPeter Brune 
5610c40d0f55SPeter Brune   Input Parameter:
5611f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5612c40d0f55SPeter Brune 
5613c40d0f55SPeter Brune   Output Parameter:
5614c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5615c40d0f55SPeter Brune .vb
5616f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5617f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5618c40d0f55SPeter Brune .ve
5619c40d0f55SPeter Brune 
5620c40d0f55SPeter Brune   Level: intermediate
5621c40d0f55SPeter Brune 
56221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`
5623c40d0f55SPeter Brune @*/
5624d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5625d71ae5a4SJacob Faibussowitsch {
5626c40d0f55SPeter Brune   PetscFunctionBegin;
5627c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56284f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5629efd4aadfSBarry Smith   *side = snes->npcside;
56303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5631c40d0f55SPeter Brune }
5632c40d0f55SPeter Brune 
56339e764e56SPeter Brune /*@
5634f6dfbefdSBarry Smith   SNESSetLineSearch - Sets the linesearch on the `SNES` instance.
56359e764e56SPeter Brune 
5636c3339decSBarry Smith   Collective
56379e764e56SPeter Brune 
56389e764e56SPeter Brune   Input Parameters:
5639f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
56409e764e56SPeter Brune - linesearch - the linesearch object
56419e764e56SPeter Brune 
5642dc4c0fb0SBarry Smith   Level: developer
5643dc4c0fb0SBarry Smith 
5644f6dfbefdSBarry Smith   Note:
5645f6dfbefdSBarry Smith   Use `SNESGetLineSearch()` to retrieve the preconditioner context (for example,
56469e764e56SPeter Brune   to configure it using the API).
56479e764e56SPeter Brune 
56481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLineSearch()`
56499e764e56SPeter Brune @*/
5650d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5651d71ae5a4SJacob Faibussowitsch {
56529e764e56SPeter Brune   PetscFunctionBegin;
56539e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5654f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
56559e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
56569566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
56579566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5658f5af7f23SKarl Rupp 
56599e764e56SPeter Brune   snes->linesearch = linesearch;
5660f5af7f23SKarl Rupp 
56613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56629e764e56SPeter Brune }
56639e764e56SPeter Brune 
5664a34ceb2aSJed Brown /*@
5665dc4c0fb0SBarry Smith   SNESGetLineSearch - Returns the line search context set with `SNESSetLineSearch()`
5666f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
56679e764e56SPeter Brune 
56689e764e56SPeter Brune   Not Collective
56699e764e56SPeter Brune 
56709e764e56SPeter Brune   Input Parameter:
5671f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56729e764e56SPeter Brune 
56739e764e56SPeter Brune   Output Parameter:
56749e764e56SPeter Brune . linesearch - linesearch context
56759e764e56SPeter Brune 
5676162e0bf5SPeter Brune   Level: beginner
56779e764e56SPeter Brune 
56781cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
56799e764e56SPeter Brune @*/
5680d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5681d71ae5a4SJacob Faibussowitsch {
56829e764e56SPeter Brune   const char *optionsprefix;
56839e764e56SPeter Brune 
56849e764e56SPeter Brune   PetscFunctionBegin;
56859e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56864f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
56879e764e56SPeter Brune   if (!snes->linesearch) {
56889566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
56899566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
56909566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
56919566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
56929566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
56939e764e56SPeter Brune   }
56949e764e56SPeter Brune   *linesearch = snes->linesearch;
56953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56969e764e56SPeter Brune }
5697