xref: /petsc/src/snes/interface/snes.c (revision 5f3c5e7ab1713b2b36ec2007ece43899b4f0dcb3)
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);
63534a8f05SLisandro Dalcin   PetscValidBoolPointer(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);
221534a8f05SLisandro Dalcin   PetscValidBoolPointer(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);
245534a8f05SLisandro Dalcin   PetscValidBoolPointer(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);
269534a8f05SLisandro Dalcin   PetscValidBoolPointer(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 
602895c21f2SBarry 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-
6153232da50SPeter Brune      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
89582738288SBarry Smith . -snes_stol                                                                   - convergence tolerance in terms of the norm
89682738288SBarry Smith                 of the change in the solution between steps
89770441072SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
898b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
899e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
900be5caee7SBarry Smith . -snes_force_iteration <force>                                                - force SNESSolve() to take at least one iteration
901b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
902b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
9034839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
904ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
905a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9063d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
907e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9083d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
9094a221d59SStefano Zampini . -snes_tr_tol <trtol>                                                         - trust region tolerance
910f362779dSJed Brown . -snes_convergence_test                                                       - <default,skip,correct_pressure> convergence test in nonlinear solver.
911f6dfbefdSBarry Smith                                default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense
912f6dfbefdSBarry Smith                                of convergence test. correct_pressure S`NESConvergedCorrectPressure()` has special handling of a pressure null space.
913fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
914fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
915fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
916fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9174619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
918459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9195e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
920e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
921e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
9225968eb51SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each KSP iteration
923b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
924e62ac41dSBarry Smith . -npc_snes_type <type>                                                        - the SNES type to use as a nonlinear preconditioner
925e62ac41dSBarry 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.
926e62ac41dSBarry 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.
92782738288SBarry Smith 
928f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
929fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9304b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
93136851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
93236851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
93336851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
93436851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
93536851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
93636851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
93782738288SBarry Smith 
938dc4c0fb0SBarry Smith   Level: beginner
939dc4c0fb0SBarry Smith 
94011ca99fdSLois Curfman McInnes   Notes:
941ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
942ec5066bdSBarry Smith 
943f6dfbefdSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix free, and computing explicitly with
944f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
94583e2fdc7SBarry Smith 
9461cc06b55SBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`
9479b94acceSBarry Smith @*/
948d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
949d71ae5a4SJacob Faibussowitsch {
9508afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
951d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
95204d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
953649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
95485385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9550f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
956c40d0f55SPeter Brune   PCSide      pcside;
957a64e098fSPeter Brune   const char *optionsprefix;
9589b94acceSBarry Smith 
9593a40ed3dSBarry Smith   PetscFunctionBegin;
9600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9619566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
962d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
963639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
965d64ed03dSBarry Smith   if (flg) {
9669566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9677adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9689566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
969d64ed03dSBarry Smith   }
9709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
9719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
972186905e3SBarry Smith 
9739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
9749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
9759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
9769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
9779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
9789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
9799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
9809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
9819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
98285385478SLisandro Dalcin 
9839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
984a8054027SBarry Smith   if (flg) {
9855f80ce2aSJacob 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");
9869566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
987a8054027SBarry Smith   }
9889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
9891baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
9909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
991e35cf81dSBarry Smith   if (flg) {
9925f80ce2aSJacob 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");
9939566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
994e35cf81dSBarry Smith   }
9959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
9961baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
99737ec4e1aSPeter Brune 
9989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
9991baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1000a8054027SBarry Smith 
10019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, sizeof(convtests) / sizeof(char *), "default", &indx, &flg));
100285385478SLisandro Dalcin   if (flg) {
100385385478SLisandro Dalcin     switch (indx) {
1004d71ae5a4SJacob Faibussowitsch     case 0:
1005d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1006d71ae5a4SJacob Faibussowitsch       break;
1007d71ae5a4SJacob Faibussowitsch     case 1:
1008d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1009d71ae5a4SJacob Faibussowitsch       break;
1010d71ae5a4SJacob Faibussowitsch     case 2:
1011d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1012d71ae5a4SJacob Faibussowitsch       break;
101385385478SLisandro Dalcin     }
101485385478SLisandro Dalcin   }
101585385478SLisandro Dalcin 
10169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10179566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1018fdacfa88SPeter Brune 
10199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10209566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1021186905e3SBarry Smith 
102285385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
102385385478SLisandro Dalcin 
10249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1025186905e3SBarry Smith 
10260f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10270f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1028a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1029186905e3SBarry Smith 
103090d69ab7SBarry Smith   flg = PETSC_FALSE;
10319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10329566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1033eabae89aSBarry Smith 
10349566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10359566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10369566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1037eabae89aSBarry Smith 
10389566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10399566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10409566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10419566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10429566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10439566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10449566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10462db13446SMatthew G. Knepley 
10479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10489566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10495180491cSLisandro Dalcin 
105090d69ab7SBarry Smith   flg = PETSC_FALSE;
10519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1052459f5d12SBarry Smith   if (flg) {
1053459f5d12SBarry Smith     PetscViewer ctx;
1054e24b481bSBarry Smith 
10559566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10569566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1057459f5d12SBarry Smith   }
10582e7541e6SPeter Brune 
105990d69ab7SBarry Smith   flg = PETSC_FALSE;
10609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10619566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1062c4421ceaSFande Kong 
1063c4421ceaSFande Kong   flg = PETSC_FALSE;
10649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10654b27c08aSLois Curfman McInnes   if (flg) {
10666cab3a1bSJed Brown     void *functx;
1067b1f624c7SBarry Smith     DM    dm;
10689566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1069800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10709566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10719566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10729566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
10739b94acceSBarry Smith   }
1074639f9d9dSBarry Smith 
107544848bc4SPeter Brune   flg = PETSC_FALSE;
10769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
10771baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
107897584545SPeter Brune 
107997584545SPeter Brune   flg = PETSC_FALSE;
10809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
108144848bc4SPeter Brune   if (flg) {
1082c52e227fSPeter Brune     DM dm;
10839566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1084800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10859566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
10869566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
108744848bc4SPeter Brune   }
108844848bc4SPeter Brune 
1089aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1091d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1092a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1093d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1094a8248277SBarry Smith   }
1095aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1097d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
10989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1099d28543b3SPeter Brune 
1100c40d0f55SPeter Brune   flg = PETSC_FALSE;
11019566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11039566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1104c40d0f55SPeter Brune 
1105e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11068a70d858SHong Zhang   /*
11078a70d858SHong Zhang     Publish convergence information using SAWs
11088a70d858SHong Zhang   */
11098a70d858SHong Zhang   flg = PETSC_FALSE;
11109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11118a70d858SHong Zhang   if (flg) {
11128a70d858SHong Zhang     void *ctx;
11139566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11149566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11158a70d858SHong Zhang   }
11168a70d858SHong Zhang #endif
11178a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1118b90c6cbeSBarry Smith   {
1119b90c6cbeSBarry Smith     PetscBool set;
1120b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11219566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11221baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1123b90c6cbeSBarry Smith   }
1124b90c6cbeSBarry Smith #endif
1125b90c6cbeSBarry Smith 
112648a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
112776b2cf59SMatthew Knepley 
1128dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11295d973c19SBarry Smith 
11305d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1131dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1132d0609cedSBarry Smith   PetscOptionsEnd();
11334bbc92c1SBarry Smith 
1134d8d34be6SBarry Smith   if (snes->linesearch) {
11359566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11369566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1137d8d34be6SBarry Smith   }
11389e764e56SPeter Brune 
11396aa5e7e9SBarry Smith   if (snes->usesksp) {
11409566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11419566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11429566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11436aa5e7e9SBarry Smith   }
11446991f827SBarry Smith 
1145b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11469566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
114848a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11491baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1150b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1152b3cd9a81SMatthew G. Knepley }
1153b3cd9a81SMatthew G. Knepley 
1154b3cd9a81SMatthew G. Knepley /*@
1155f6dfbefdSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously set from options
1156b3cd9a81SMatthew G. Knepley 
1157c3339decSBarry Smith   Collective
1158b3cd9a81SMatthew G. Knepley 
1159b3cd9a81SMatthew G. Knepley   Input Parameter:
1160f6dfbefdSBarry Smith . snes - the `SNES` context
1161b3cd9a81SMatthew G. Knepley 
1162b3cd9a81SMatthew G. Knepley   Level: beginner
1163b3cd9a81SMatthew G. Knepley 
11641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1165b3cd9a81SMatthew G. Knepley @*/
1166d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1167d71ae5a4SJacob Faibussowitsch {
1168b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11699566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11719b94acceSBarry Smith }
11729b94acceSBarry Smith 
1173bb9467b5SJed Brown /*@C
1174d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1175d25893d9SBarry Smith   the nonlinear solvers.
1176d25893d9SBarry Smith 
1177dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1178d25893d9SBarry Smith 
1179d25893d9SBarry Smith   Input Parameters:
1180f6dfbefdSBarry Smith + snes    - the `SNES` context
1181d25893d9SBarry Smith . compute - function to compute the context
1182d25893d9SBarry Smith - destroy - function to destroy the context
1183d25893d9SBarry Smith 
1184d25893d9SBarry Smith   Level: intermediate
1185d25893d9SBarry Smith 
1186f6dfbefdSBarry Smith   Note:
1187f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1188f6dfbefdSBarry Smith 
1189f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1190f6dfbefdSBarry Smith 
11911cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetComputeApplicationContext()`, `SNESSetApplicationContext()`
1192d25893d9SBarry Smith @*/
1193d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES, void **), PetscErrorCode (*destroy)(void **))
1194d71ae5a4SJacob Faibussowitsch {
1195d25893d9SBarry Smith   PetscFunctionBegin;
1196d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1197d25893d9SBarry Smith   snes->ops->usercompute = compute;
1198d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
11993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1200d25893d9SBarry Smith }
1201a847f771SSatish Balay 
1202b07ff414SBarry Smith /*@
1203f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12049b94acceSBarry Smith 
1205c3339decSBarry Smith   Logically Collective
1206fee21e36SBarry Smith 
1207c7afd0dbSLois Curfman McInnes   Input Parameters:
1208f6dfbefdSBarry Smith + snes - the `SNES` context
1209c7afd0dbSLois Curfman McInnes - usrP - optional user context
1210c7afd0dbSLois Curfman McInnes 
121136851e7fSLois Curfman McInnes   Level: intermediate
121236851e7fSLois Curfman McInnes 
1213f6dfbefdSBarry Smith   Notes:
1214f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1215f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1216f6dfbefdSBarry Smith 
1217f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1218f6dfbefdSBarry Smith 
1219e4094ef1SJacob Faibussowitsch   Fortran Notes:
1220dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1221daf670e6SBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1222daf670e6SBarry Smith 
12231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12249b94acceSBarry Smith @*/
1225d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1226d71ae5a4SJacob Faibussowitsch {
1227b07ff414SBarry Smith   KSP ksp;
12281b2093e4SBarry Smith 
12293a40ed3dSBarry Smith   PetscFunctionBegin;
12300700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12319566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12329566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12339b94acceSBarry Smith   snes->user = usrP;
12343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12359b94acceSBarry Smith }
123674679c65SBarry Smith 
1237b07ff414SBarry Smith /*@
12389b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1239f6dfbefdSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or with `SNESSetComputeApplicationContext()`
12409b94acceSBarry Smith 
1241c7afd0dbSLois Curfman McInnes   Not Collective
1242c7afd0dbSLois Curfman McInnes 
12439b94acceSBarry Smith   Input Parameter:
1244f6dfbefdSBarry Smith . snes - `SNES` context
12459b94acceSBarry Smith 
12469b94acceSBarry Smith   Output Parameter:
12479b94acceSBarry Smith . usrP - user context
12489b94acceSBarry Smith 
124936851e7fSLois Curfman McInnes   Level: intermediate
125036851e7fSLois Curfman McInnes 
1251e4094ef1SJacob Faibussowitsch   Fortran Notes:
1252dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1253dc4c0fb0SBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1254dc4c0fb0SBarry Smith 
12551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`
12569b94acceSBarry Smith @*/
1257d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1258d71ae5a4SJacob Faibussowitsch {
12593a40ed3dSBarry Smith   PetscFunctionBegin;
12600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1261e71120c6SJed Brown   *(void **)usrP = snes->user;
12623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12639b94acceSBarry Smith }
126474679c65SBarry Smith 
12659b94acceSBarry Smith /*@
1266f6dfbefdSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix free finite difference matrix vector products to apply the Jacobian.
12673565c898SBarry Smith 
1268dc4c0fb0SBarry Smith   Logically Collective
12693565c898SBarry Smith 
12703565c898SBarry Smith   Input Parameters:
1271f6dfbefdSBarry Smith + snes        - `SNES` context
1272f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1273f6dfbefdSBarry 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
1274f6dfbefdSBarry Smith    this option no matrix element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
12753565c898SBarry Smith 
1276f6dfbefdSBarry Smith   Options Database Keys:
1277f6dfbefdSBarry Smith + -snes_mf_operator - use matrix free only for the mat operator
1278f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1279ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1280ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
12813565c898SBarry Smith 
12823565c898SBarry Smith   Level: intermediate
12833565c898SBarry Smith 
1284f6dfbefdSBarry Smith   Note:
1285dc4c0fb0SBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free, and computing explicitly with
1286f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1287ec5066bdSBarry Smith 
12881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`
12893565c898SBarry Smith @*/
1290d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1291d71ae5a4SJacob Faibussowitsch {
12923565c898SBarry Smith   PetscFunctionBegin;
12933565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
129488b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
129588b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
12964ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
12973565c898SBarry Smith   snes->mf_operator = mf_operator;
12983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12993565c898SBarry Smith }
13003565c898SBarry Smith 
13013565c898SBarry Smith /*@
1302dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13033565c898SBarry Smith 
1304f6dfbefdSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI ranks
13053565c898SBarry Smith 
13063565c898SBarry Smith   Input Parameter:
1307f6dfbefdSBarry Smith . snes - `SNES` context
13083565c898SBarry Smith 
13093565c898SBarry Smith   Output Parameters:
1310f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1311f6dfbefdSBarry 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
13123565c898SBarry Smith 
13133565c898SBarry Smith   Level: intermediate
13143565c898SBarry Smith 
13151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13163565c898SBarry Smith @*/
1317d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1318d71ae5a4SJacob Faibussowitsch {
13193565c898SBarry Smith   PetscFunctionBegin;
13203565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13213565c898SBarry Smith   if (mf) *mf = snes->mf;
13223565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13243565c898SBarry Smith }
13253565c898SBarry Smith 
13263565c898SBarry Smith /*@
1327c8228a4eSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed
1328c8228a4eSBarry Smith   at this time.
13299b94acceSBarry Smith 
1330c7afd0dbSLois Curfman McInnes   Not Collective
1331c7afd0dbSLois Curfman McInnes 
13329b94acceSBarry Smith   Input Parameter:
1333f6dfbefdSBarry Smith . snes - `SNES` context
13349b94acceSBarry Smith 
13359b94acceSBarry Smith   Output Parameter:
13369b94acceSBarry Smith . iter - iteration number
13379b94acceSBarry Smith 
1338dc4c0fb0SBarry Smith   Level: intermediate
1339dc4c0fb0SBarry Smith 
1340c8228a4eSBarry Smith   Notes:
1341c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1342c8228a4eSBarry Smith 
1343c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1344f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
134508405cd6SLois Curfman McInnes .vb
134608405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
134708405cd6SLois Curfman McInnes       if (!(it % 2)) {
134808405cd6SLois Curfman McInnes         [compute Jacobian here]
134908405cd6SLois Curfman McInnes       }
135008405cd6SLois Curfman McInnes .ve
1351f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1352f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1353c8228a4eSBarry Smith 
1354f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1355c04deec6SBarry Smith 
13561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`
13579b94acceSBarry Smith @*/
1358d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1359d71ae5a4SJacob Faibussowitsch {
13603a40ed3dSBarry Smith   PetscFunctionBegin;
13610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13624482741eSBarry Smith   PetscValidIntPointer(iter, 2);
13639b94acceSBarry Smith   *iter = snes->iter;
13643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13659b94acceSBarry Smith }
136674679c65SBarry Smith 
1367360c497dSPeter Brune /*@
1368360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1369360c497dSPeter Brune 
1370360c497dSPeter Brune   Not Collective
1371360c497dSPeter Brune 
1372d8d19677SJose E. Roman   Input Parameters:
1373f6dfbefdSBarry Smith + snes - `SNES` context
1374a2b725a8SWilliam Gropp - iter - iteration number
1375360c497dSPeter Brune 
1376360c497dSPeter Brune   Level: developer
1377360c497dSPeter Brune 
13781cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1379360c497dSPeter Brune @*/
1380d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1381d71ae5a4SJacob Faibussowitsch {
1382360c497dSPeter Brune   PetscFunctionBegin;
1383360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13849566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1385360c497dSPeter Brune   snes->iter = iter;
13869566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
13873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1388360c497dSPeter Brune }
1389360c497dSPeter Brune 
13909b94acceSBarry Smith /*@
1391b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
13929b94acceSBarry Smith   attempted by the nonlinear solver.
13939b94acceSBarry Smith 
1394c7afd0dbSLois Curfman McInnes   Not Collective
1395c7afd0dbSLois Curfman McInnes 
13969b94acceSBarry Smith   Input Parameter:
1397f6dfbefdSBarry Smith . snes - `SNES` context
13989b94acceSBarry Smith 
13999b94acceSBarry Smith   Output Parameter:
14009b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14019b94acceSBarry Smith 
1402dc4c0fb0SBarry Smith   Level: intermediate
1403dc4c0fb0SBarry Smith 
1404f6dfbefdSBarry Smith   Note:
1405f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1406c96a6f78SLois Curfman McInnes 
14071cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1408db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14099b94acceSBarry Smith @*/
1410d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1411d71ae5a4SJacob Faibussowitsch {
14123a40ed3dSBarry Smith   PetscFunctionBegin;
14130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14144482741eSBarry Smith   PetscValidIntPointer(nfails, 2);
141550ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
141750ffb88aSMatthew Knepley }
141850ffb88aSMatthew Knepley 
141950ffb88aSMatthew Knepley /*@
1420b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1421f6dfbefdSBarry Smith   attempted by the nonlinear solver before it gives up and generates an error
142250ffb88aSMatthew Knepley 
142350ffb88aSMatthew Knepley   Not Collective
142450ffb88aSMatthew Knepley 
142550ffb88aSMatthew Knepley   Input Parameters:
1426f6dfbefdSBarry Smith + snes     - `SNES` context
142750ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps
142850ffb88aSMatthew Knepley 
142950ffb88aSMatthew Knepley   Level: intermediate
143050ffb88aSMatthew Knepley 
14311cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1432db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
143350ffb88aSMatthew Knepley @*/
1434d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1435d71ae5a4SJacob Faibussowitsch {
143650ffb88aSMatthew Knepley   PetscFunctionBegin;
14370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
143850ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
14393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
144050ffb88aSMatthew Knepley }
144150ffb88aSMatthew Knepley 
144250ffb88aSMatthew Knepley /*@
1443b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1444f6dfbefdSBarry Smith   attempted by the nonlinear solver before it gives up and generates an error
144550ffb88aSMatthew Knepley 
144650ffb88aSMatthew Knepley   Not Collective
144750ffb88aSMatthew Knepley 
144850ffb88aSMatthew Knepley   Input Parameter:
144920f4b53cSBarry Smith . snes - `SNES` context
145050ffb88aSMatthew Knepley 
145150ffb88aSMatthew Knepley   Output Parameter:
145250ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
145350ffb88aSMatthew Knepley 
145450ffb88aSMatthew Knepley   Level: intermediate
145550ffb88aSMatthew Knepley 
14561cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1457db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
145850ffb88aSMatthew Knepley @*/
1459d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1460d71ae5a4SJacob Faibussowitsch {
146150ffb88aSMatthew Knepley   PetscFunctionBegin;
14620700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14634482741eSBarry Smith   PetscValidIntPointer(maxFails, 2);
146450ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
14653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14669b94acceSBarry Smith }
1467a847f771SSatish Balay 
14682541af92SBarry Smith /*@
14692541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1470f6dfbefdSBarry Smith   done by the `SNES` object
14712541af92SBarry Smith 
14722541af92SBarry Smith   Not Collective
14732541af92SBarry Smith 
14742541af92SBarry Smith   Input Parameter:
1475f6dfbefdSBarry Smith . snes - `SNES` context
14762541af92SBarry Smith 
14772541af92SBarry Smith   Output Parameter:
14782541af92SBarry Smith . nfuncs - number of evaluations
14792541af92SBarry Smith 
14802541af92SBarry Smith   Level: intermediate
14812541af92SBarry Smith 
1482f6dfbefdSBarry Smith   Note:
1483f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1484971e163fSPeter Brune 
14851cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
14862541af92SBarry Smith @*/
1487d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1488d71ae5a4SJacob Faibussowitsch {
14892541af92SBarry Smith   PetscFunctionBegin;
14900700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14912541af92SBarry Smith   PetscValidIntPointer(nfuncs, 2);
14922541af92SBarry Smith   *nfuncs = snes->nfuncs;
14933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14942541af92SBarry Smith }
14952541af92SBarry Smith 
14963d4c4710SBarry Smith /*@
14973d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
14983d4c4710SBarry Smith   linear solvers.
14993d4c4710SBarry Smith 
15003d4c4710SBarry Smith   Not Collective
15013d4c4710SBarry Smith 
15023d4c4710SBarry Smith   Input Parameter:
1503f6dfbefdSBarry Smith . snes - `SNES` context
15043d4c4710SBarry Smith 
15053d4c4710SBarry Smith   Output Parameter:
15063d4c4710SBarry Smith . nfails - number of failed solves
15073d4c4710SBarry Smith 
1508f6dfbefdSBarry Smith   Options Database Key:
15099d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15109d85da0cSMatthew G. Knepley 
1511f6dfbefdSBarry Smith   Level: intermediate
1512f6dfbefdSBarry Smith 
1513f6dfbefdSBarry Smith   Note:
1514f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15153d4c4710SBarry Smith 
15161cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15173d4c4710SBarry Smith @*/
1518d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1519d71ae5a4SJacob Faibussowitsch {
15203d4c4710SBarry Smith   PetscFunctionBegin;
15210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15223d4c4710SBarry Smith   PetscValidIntPointer(nfails, 2);
15233d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15253d4c4710SBarry Smith }
15263d4c4710SBarry Smith 
15273d4c4710SBarry Smith /*@
15283d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1529f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15303d4c4710SBarry Smith 
1531c3339decSBarry Smith   Logically Collective
15323d4c4710SBarry Smith 
15333d4c4710SBarry Smith   Input Parameters:
1534f6dfbefdSBarry Smith + snes     - `SNES` context
15353d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures
15363d4c4710SBarry Smith 
1537f6dfbefdSBarry Smith   Options Database Key:
15389d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15399d85da0cSMatthew G. Knepley 
1540dc4c0fb0SBarry Smith   Level: intermediate
1541dc4c0fb0SBarry Smith 
1542f6dfbefdSBarry Smith   Note:
1543f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
15443d4c4710SBarry Smith 
15451cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
15463d4c4710SBarry Smith @*/
1547d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1548d71ae5a4SJacob Faibussowitsch {
15493d4c4710SBarry Smith   PetscFunctionBegin;
15500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1551c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
15523d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
15533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15543d4c4710SBarry Smith }
15553d4c4710SBarry Smith 
15563d4c4710SBarry Smith /*@
15573d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1558f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
15593d4c4710SBarry Smith 
15603d4c4710SBarry Smith   Not Collective
15613d4c4710SBarry Smith 
15623d4c4710SBarry Smith   Input Parameter:
1563f6dfbefdSBarry Smith . snes - `SNES` context
15643d4c4710SBarry Smith 
15653d4c4710SBarry Smith   Output Parameter:
15663d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
15673d4c4710SBarry Smith 
15683d4c4710SBarry Smith   Level: intermediate
15693d4c4710SBarry Smith 
1570f6dfbefdSBarry Smith   Note:
1571f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
15723d4c4710SBarry Smith 
15731cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
15743d4c4710SBarry Smith @*/
1575d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1576d71ae5a4SJacob Faibussowitsch {
15773d4c4710SBarry Smith   PetscFunctionBegin;
15780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15793d4c4710SBarry Smith   PetscValidIntPointer(maxFails, 2);
15803d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
15813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15823d4c4710SBarry Smith }
15833d4c4710SBarry Smith 
1584c96a6f78SLois Curfman McInnes /*@
1585b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1586c96a6f78SLois Curfman McInnes   used by the nonlinear solver.
1587c96a6f78SLois Curfman McInnes 
1588c7afd0dbSLois Curfman McInnes   Not Collective
1589c7afd0dbSLois Curfman McInnes 
1590c96a6f78SLois Curfman McInnes   Input Parameter:
1591f6dfbefdSBarry Smith . snes - `SNES` context
1592c96a6f78SLois Curfman McInnes 
1593c96a6f78SLois Curfman McInnes   Output Parameter:
1594c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1595c96a6f78SLois Curfman McInnes 
1596dc4c0fb0SBarry Smith   Level: intermediate
1597dc4c0fb0SBarry Smith 
1598c96a6f78SLois Curfman McInnes   Notes:
1599f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1600c96a6f78SLois Curfman McInnes 
1601f6dfbefdSBarry 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
1602f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1603010be392SBarry Smith 
16041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1605c96a6f78SLois Curfman McInnes @*/
1606d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1607d71ae5a4SJacob Faibussowitsch {
16083a40ed3dSBarry Smith   PetscFunctionBegin;
16090700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16104482741eSBarry Smith   PetscValidIntPointer(lits, 2);
1611c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1613c96a6f78SLois Curfman McInnes }
1614c96a6f78SLois Curfman McInnes 
1615971e163fSPeter Brune /*@
1616971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1617f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1618971e163fSPeter Brune 
1619c3339decSBarry Smith   Logically Collective
1620971e163fSPeter Brune 
1621d8d19677SJose E. Roman   Input Parameters:
1622f6dfbefdSBarry Smith + snes  - `SNES` context
1623f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1624971e163fSPeter Brune 
1625971e163fSPeter Brune   Level: developer
1626971e163fSPeter Brune 
16271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1628971e163fSPeter Brune @*/
1629d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1630d71ae5a4SJacob Faibussowitsch {
1631971e163fSPeter Brune   PetscFunctionBegin;
1632971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1633971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1634971e163fSPeter Brune   snes->counters_reset = reset;
16353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1636971e163fSPeter Brune }
1637971e163fSPeter Brune 
16382999313aSBarry Smith /*@
1639f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16402999313aSBarry Smith 
1641f6dfbefdSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same MPI_Comm
16422999313aSBarry Smith 
16432999313aSBarry Smith   Input Parameters:
1644f6dfbefdSBarry Smith + snes - the `SNES` context
1645f6dfbefdSBarry Smith - ksp  - the `KSP` context
16462999313aSBarry Smith 
1647dc4c0fb0SBarry Smith   Level: developer
1648dc4c0fb0SBarry Smith 
16492999313aSBarry Smith   Notes:
1650f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
16512999313aSBarry Smith   so this routine is rarely needed.
16522999313aSBarry Smith 
1653f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
16542999313aSBarry Smith   decreased by one.
16552999313aSBarry Smith 
16561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
16572999313aSBarry Smith @*/
1658d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1659d71ae5a4SJacob Faibussowitsch {
16602999313aSBarry Smith   PetscFunctionBegin;
16610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16620700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
16632999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
16649566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
16659566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
16662999313aSBarry Smith   snes->ksp = ksp;
16673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16682999313aSBarry Smith }
16692999313aSBarry Smith 
167052baeb72SSatish Balay /*@
1671dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
16729b94acceSBarry Smith 
1673d083f849SBarry Smith   Collective
1674c7afd0dbSLois Curfman McInnes 
1675f6dfbefdSBarry Smith   Input Parameter:
1676906ed7ccSBarry Smith . comm - MPI communicator
16779b94acceSBarry Smith 
16789b94acceSBarry Smith   Output Parameter:
167920f4b53cSBarry Smith . outsnes - the new `SNES` context
16809b94acceSBarry Smith 
1681c7afd0dbSLois Curfman McInnes   Options Database Keys:
1682dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1683dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1684dc4c0fb0SBarry Smith                as set by `SNESSetJacobian()`
1685dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1686c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1687c1f60f51SBarry Smith 
168836851e7fSLois Curfman McInnes   Level: beginner
168936851e7fSLois Curfman McInnes 
169095452b02SPatrick Sanan   Developer Notes:
1691f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1692efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1693f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1694f6dfbefdSBarry Smith   in `SNESView()`.
1695efd4aadfSBarry Smith 
1696f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1697f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1698f6dfbefdSBarry Smith 
1699dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1700efd4aadfSBarry Smith 
1701e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
17029b94acceSBarry Smith @*/
1703d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1704d71ae5a4SJacob Faibussowitsch {
17059b94acceSBarry Smith   SNES       snes;
1706fa9f3622SBarry Smith   SNESKSPEW *kctx;
170737fcc0dbSBarry Smith 
17083a40ed3dSBarry Smith   PetscFunctionBegin;
1709ed1caa07SMatthew Knepley   PetscValidPointer(outsnes, 2);
17100298fd71SBarry Smith   *outsnes = NULL;
17119566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17128ba1e511SMatthew Knepley 
17139566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17147adad957SLisandro Dalcin 
17158d359177SBarry Smith   snes->ops->converged       = SNESConvergedDefault;
17162c155ee1SBarry Smith   snes->usesksp              = PETSC_TRUE;
171788976e71SPeter Brune   snes->tolerancesset        = PETSC_FALSE;
17189b94acceSBarry Smith   snes->max_its              = 50;
17199750a799SBarry Smith   snes->max_funcs            = 10000;
17209b94acceSBarry Smith   snes->norm                 = 0.0;
1721c1e67a49SFande Kong   snes->xnorm                = 0.0;
1722c1e67a49SFande Kong   snes->ynorm                = 0.0;
1723365a6726SPeter Brune   snes->normschedule         = SNES_NORM_ALWAYS;
17246c67d002SPeter Brune   snes->functype             = SNES_FUNCTION_DEFAULT;
17258ca48ce9SPierre Jolivet   snes->rtol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
1726b4874afaSBarry Smith   snes->ttol                 = 0.0;
17278ca48ce9SPierre Jolivet   snes->abstol               = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50;
17288ca48ce9SPierre Jolivet   snes->stol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
17298ca48ce9SPierre Jolivet   snes->deltatol             = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12;
1730e37c518bSBarry Smith   snes->divtol               = 1.e4;
1731e37c518bSBarry Smith   snes->rnorm0               = 0;
17329b94acceSBarry Smith   snes->nfuncs               = 0;
173350ffb88aSMatthew Knepley   snes->numFailures          = 0;
173450ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17357a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1736e35cf81dSBarry Smith   snes->lagjacobian          = 1;
173737ec4e1aSPeter Brune   snes->jac_iter             = 0;
173837ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1739a8054027SBarry Smith   snes->lagpreconditioner    = 1;
174037ec4e1aSPeter Brune   snes->pre_iter             = 0;
174137ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1742639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1743c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17449e5d0892SLisandro Dalcin   snes->data                 = NULL;
17454dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1746186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17476f24a144SLois Curfman McInnes   snes->nwork                = 0;
17489e5d0892SLisandro Dalcin   snes->work                 = NULL;
174958c9b817SLisandro Dalcin   snes->nvwork               = 0;
17509e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1751758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1752758f92a0SBarry Smith   snes->conv_hist_max        = 0;
17530298fd71SBarry Smith   snes->conv_hist            = NULL;
17540298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1755758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1756971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1757e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1758184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1759efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1760b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1761c40d0f55SPeter Brune 
1762d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1763d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1764d8f46077SPeter Brune   snes->mf_version  = 1;
1765d8f46077SPeter Brune 
17663d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
17673d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
17683d4c4710SBarry Smith 
1769349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
177076bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1771349187a7SBarry Smith 
17724fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
17734fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
17744fc747eaSLawrence Mitchell 
17759b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
17764dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1777f5af7f23SKarl Rupp 
17789b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
17799b94acceSBarry Smith   kctx->version     = 2;
17800f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
17819b94acceSBarry Smith                              this was too large for some test cases */
178275567043SBarry Smith   kctx->rtol_last   = 0.0;
17830f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
17849b94acceSBarry Smith   kctx->gamma       = 1.0;
17850f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
178671f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
17870f0abf79SStefano Zampini   kctx->threshold   = 0.1;
178875567043SBarry Smith   kctx->lresid_last = 0.0;
178975567043SBarry Smith   kctx->norm_last   = 0.0;
17909b94acceSBarry Smith 
17910f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
17920f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
17930f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
17940f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
17950f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
17960f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
17970f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
17980f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
17990f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
18000f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
18010f0abf79SStefano Zampini 
18029b94acceSBarry Smith   *outsnes = snes;
18033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18049b94acceSBarry Smith }
18059b94acceSBarry Smith 
180688f0584fSBarry Smith /*MC
1807f6dfbefdSBarry Smith     SNESFunction - Functional form used to convey the nonlinear function to `SNES` in `SNESSetFunction()`
180888f0584fSBarry Smith 
180988f0584fSBarry Smith      Synopsis:
1810411c0326SBarry Smith      #include "petscsnes.h"
1811411c0326SBarry Smith      PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
181288f0584fSBarry Smith 
1813c3339decSBarry Smith      Collective
18141843f636SBarry Smith 
181588f0584fSBarry Smith      Input Parameters:
1816f6dfbefdSBarry Smith +     snes - the `SNES` context
181788f0584fSBarry Smith .     x    - state at which to evaluate residual
1818f6dfbefdSBarry Smith -     ctx     - optional user-defined function context, passed in with `SNESSetFunction()`
181988f0584fSBarry Smith 
182088f0584fSBarry Smith      Output Parameter:
182188f0584fSBarry Smith .     f  - vector to put residual (function value)
182288f0584fSBarry Smith 
1823878cb397SSatish Balay    Level: intermediate
1824878cb397SSatish Balay 
18251cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESGetFunction()`
182688f0584fSBarry Smith M*/
182788f0584fSBarry Smith 
18289b94acceSBarry Smith /*@C
18299b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1830f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
18319b94acceSBarry Smith   equations.
18329b94acceSBarry Smith 
1833c3339decSBarry Smith   Logically Collective
1834fee21e36SBarry Smith 
1835c7afd0dbSLois Curfman McInnes   Input Parameters:
1836f6dfbefdSBarry Smith + snes - the `SNES` context
1837dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
183820f4b53cSBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunction`
1839c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1840dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
18419b94acceSBarry Smith 
184236851e7fSLois Curfman McInnes   Level: beginner
184336851e7fSLois Curfman McInnes 
18441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunction`
18459b94acceSBarry Smith @*/
1846d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunction(SNES snes, Vec r, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
1847d71ae5a4SJacob Faibussowitsch {
18486cab3a1bSJed Brown   DM dm;
18496cab3a1bSJed Brown 
18503a40ed3dSBarry Smith   PetscFunctionBegin;
18510700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1852d2a683ecSLisandro Dalcin   if (r) {
1853d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1854d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18559566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18569566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
185785385478SLisandro Dalcin     snes->vec_func = r;
1858d2a683ecSLisandro Dalcin   }
18599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18609566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
186148a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18639b94acceSBarry Smith }
18649b94acceSBarry Smith 
1865e4ed7901SPeter Brune /*@C
18660b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1867e4ed7901SPeter Brune 
1868c3339decSBarry Smith   Logically Collective
1869e4ed7901SPeter Brune 
1870e4ed7901SPeter Brune   Input Parameters:
1871f6dfbefdSBarry Smith + snes - the `SNES` context
1872e4ed7901SPeter Brune - f    - vector to store function value
1873e4ed7901SPeter Brune 
1874dc4c0fb0SBarry Smith   Level: developer
1875dc4c0fb0SBarry Smith 
1876e4ed7901SPeter Brune   Notes:
1877e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1878e4ed7901SPeter Brune 
1879f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1880e4ed7901SPeter Brune 
18811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1882e4ed7901SPeter Brune @*/
1883d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1884d71ae5a4SJacob Faibussowitsch {
1885e4ed7901SPeter Brune   Vec vec_func;
1886e4ed7901SPeter Brune 
1887e4ed7901SPeter Brune   PetscFunctionBegin;
1888e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1889e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1890e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1891efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1892902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
18933ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1894902f982fSPeter Brune   }
18959566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
18969566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1897f5af7f23SKarl Rupp 
1898217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
18993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1900e4ed7901SPeter Brune }
1901e4ed7901SPeter Brune 
1902534ebe21SPeter Brune /*@
1903f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1904f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1905534ebe21SPeter Brune 
1906c3339decSBarry Smith   Logically Collective
1907534ebe21SPeter Brune 
1908534ebe21SPeter Brune   Input Parameters:
1909f6dfbefdSBarry Smith + snes         - the `SNES` context
1910365a6726SPeter Brune - normschedule - the frequency of norm computation
1911534ebe21SPeter Brune 
1912517f1916SMatthew G. Knepley   Options Database Key:
191367b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1914517f1916SMatthew G. Knepley 
1915dc4c0fb0SBarry Smith   Level: advanced
1916dc4c0fb0SBarry Smith 
1917534ebe21SPeter Brune   Notes:
1918f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1919534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
1920534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1921f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1922534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
1923534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
1924534ebe21SPeter Brune   their solution.
1925534ebe21SPeter Brune 
1926e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
1927534ebe21SPeter Brune @*/
1928d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1929d71ae5a4SJacob Faibussowitsch {
1930534ebe21SPeter Brune   PetscFunctionBegin;
1931534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1932365a6726SPeter Brune   snes->normschedule = normschedule;
19333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1934534ebe21SPeter Brune }
1935534ebe21SPeter Brune 
1936534ebe21SPeter Brune /*@
1937f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1938f6dfbefdSBarry Smith   of the `SNES` method.
1939534ebe21SPeter Brune 
1940c3339decSBarry Smith   Logically Collective
1941534ebe21SPeter Brune 
1942534ebe21SPeter Brune   Input Parameters:
1943f6dfbefdSBarry Smith + snes         - the `SNES` context
1944365a6726SPeter Brune - normschedule - the type of the norm used
1945534ebe21SPeter Brune 
1946534ebe21SPeter Brune   Level: advanced
1947534ebe21SPeter Brune 
19481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1949534ebe21SPeter Brune @*/
1950d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1951d71ae5a4SJacob Faibussowitsch {
1952534ebe21SPeter Brune   PetscFunctionBegin;
1953534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1954365a6726SPeter Brune   *normschedule = snes->normschedule;
19553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1956534ebe21SPeter Brune }
1957534ebe21SPeter Brune 
1958c5ce4427SMatthew G. Knepley /*@
1959c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1960c5ce4427SMatthew G. Knepley 
1961c3339decSBarry Smith   Logically Collective
1962c5ce4427SMatthew G. Knepley 
1963c5ce4427SMatthew G. Knepley   Input Parameters:
1964f6dfbefdSBarry Smith + snes - the `SNES` context
1965f6dfbefdSBarry Smith - norm - the value of the norm
1966c5ce4427SMatthew G. Knepley 
1967c5ce4427SMatthew G. Knepley   Level: developer
1968c5ce4427SMatthew G. Knepley 
19691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1970c5ce4427SMatthew G. Knepley @*/
1971d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1972d71ae5a4SJacob Faibussowitsch {
1973c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1974c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1975c5ce4427SMatthew G. Knepley   snes->norm = norm;
19763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1977c5ce4427SMatthew G. Knepley }
1978c5ce4427SMatthew G. Knepley 
1979c5ce4427SMatthew G. Knepley /*@
1980c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
1981c5ce4427SMatthew G. Knepley 
1982c5ce4427SMatthew G. Knepley   Not Collective
1983c5ce4427SMatthew G. Knepley 
1984c5ce4427SMatthew G. Knepley   Input Parameter:
1985f6dfbefdSBarry Smith . snes - the `SNES` context
1986c5ce4427SMatthew G. Knepley 
1987c5ce4427SMatthew G. Knepley   Output Parameter:
1988c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
1989c5ce4427SMatthew G. Knepley 
1990c5ce4427SMatthew G. Knepley   Level: developer
1991c5ce4427SMatthew G. Knepley 
19921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1993c5ce4427SMatthew G. Knepley @*/
1994d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
1995d71ae5a4SJacob Faibussowitsch {
1996c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1997c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1998dadcf809SJacob Faibussowitsch   PetscValidRealPointer(norm, 2);
1999c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2001c5ce4427SMatthew G. Knepley }
2002c5ce4427SMatthew G. Knepley 
2003c1e67a49SFande Kong /*@
2004f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2005c1e67a49SFande Kong 
2006c1e67a49SFande Kong   Not Collective
2007c1e67a49SFande Kong 
2008c1e67a49SFande Kong   Input Parameter:
2009f6dfbefdSBarry Smith . snes - the `SNES` context
2010c1e67a49SFande Kong 
2011c1e67a49SFande Kong   Output Parameter:
2012c1e67a49SFande Kong . ynorm - the last computed update norm
2013c1e67a49SFande Kong 
2014c1e67a49SFande Kong   Level: developer
2015c1e67a49SFande Kong 
2016f6dfbefdSBarry Smith   Note:
2017f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2018f6dfbefdSBarry Smith 
20191cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2020c1e67a49SFande Kong @*/
2021d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2022d71ae5a4SJacob Faibussowitsch {
2023c1e67a49SFande Kong   PetscFunctionBegin;
2024c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2025dadcf809SJacob Faibussowitsch   PetscValidRealPointer(ynorm, 2);
2026c1e67a49SFande Kong   *ynorm = snes->ynorm;
20273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2028c1e67a49SFande Kong }
2029c1e67a49SFande Kong 
2030c1e67a49SFande Kong /*@
20314591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2032c1e67a49SFande Kong 
2033c1e67a49SFande Kong   Not Collective
2034c1e67a49SFande Kong 
2035c1e67a49SFande Kong   Input Parameter:
2036f6dfbefdSBarry Smith . snes - the `SNES` context
2037c1e67a49SFande Kong 
2038c1e67a49SFande Kong   Output Parameter:
2039c1e67a49SFande Kong . xnorm - the last computed solution norm
2040c1e67a49SFande Kong 
2041c1e67a49SFande Kong   Level: developer
2042c1e67a49SFande Kong 
20431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2044c1e67a49SFande Kong @*/
2045d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2046d71ae5a4SJacob Faibussowitsch {
2047c1e67a49SFande Kong   PetscFunctionBegin;
2048c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2049dadcf809SJacob Faibussowitsch   PetscValidRealPointer(xnorm, 2);
2050c1e67a49SFande Kong   *xnorm = snes->xnorm;
20513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2052c1e67a49SFande Kong }
2053c1e67a49SFande Kong 
205447073ea2SPeter Brune /*@C
2055f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2056f6dfbefdSBarry Smith   of the `SNES` method.
205747073ea2SPeter Brune 
2058c3339decSBarry Smith   Logically Collective
205947073ea2SPeter Brune 
206047073ea2SPeter Brune   Input Parameters:
2061f6dfbefdSBarry Smith + snes - the `SNES` context
2062f6dfbefdSBarry Smith - type - the function type
206347073ea2SPeter Brune 
206447073ea2SPeter Brune   Level: developer
206547073ea2SPeter Brune 
2066f6dfbefdSBarry Smith   Notes:
2067f6dfbefdSBarry Smith   Possible values of the function type
2068f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType`
2069f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2070f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()`
2071f6dfbefdSBarry Smith 
2072f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2073f6dfbefdSBarry Smith 
20741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
207547073ea2SPeter Brune @*/
2076d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2077d71ae5a4SJacob Faibussowitsch {
207847073ea2SPeter Brune   PetscFunctionBegin;
207947073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
208047073ea2SPeter Brune   snes->functype = type;
20813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208247073ea2SPeter Brune }
208347073ea2SPeter Brune 
208447073ea2SPeter Brune /*@C
2085f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
208647073ea2SPeter Brune   of the SNES method.
208747073ea2SPeter Brune 
2088c3339decSBarry Smith   Logically Collective
208947073ea2SPeter Brune 
209047073ea2SPeter Brune   Input Parameters:
2091f6dfbefdSBarry Smith + snes - the `SNES` context
2092f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
209347073ea2SPeter Brune 
209447073ea2SPeter Brune   Level: advanced
209547073ea2SPeter Brune 
20961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
209747073ea2SPeter Brune @*/
2098d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2099d71ae5a4SJacob Faibussowitsch {
210047073ea2SPeter Brune   PetscFunctionBegin;
210147073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
210247073ea2SPeter Brune   *type = snes->functype;
21033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2104534ebe21SPeter Brune }
2105534ebe21SPeter Brune 
2106c79ef259SPeter Brune /*@C
2107be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2108c79ef259SPeter Brune   use with composed nonlinear solvers.
2109c79ef259SPeter Brune 
2110c79ef259SPeter Brune   Input Parameters:
2111dc4c0fb0SBarry Smith + snes - the `SNES` context
211237fdd005SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel
2113c79ef259SPeter Brune - ctx  - [optional] user-defined context for private data for the
2114dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2115c79ef259SPeter Brune 
211620f4b53cSBarry Smith   Calling sequence of `f`:
21170b4db180SJacob Faibussowitsch $ PetscErrorCode f(SNES snes, Vec X, Vec B, void *ctx);
2118f6dfbefdSBarry Smith + snes - the `SNES` context
2119f6dfbefdSBarry Smith . X    - the current solution
2120dc4c0fb0SBarry Smith . B    - the right hand side vector (which may be `NULL`)
2121f6dfbefdSBarry Smith - ctx  - a user provided context
2122f6dfbefdSBarry Smith 
2123dc4c0fb0SBarry Smith   Level: intermediate
2124dc4c0fb0SBarry Smith 
2125f6dfbefdSBarry Smith   Note:
2126f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2127f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2128c79ef259SPeter Brune 
21291cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`
2130c79ef259SPeter Brune @*/
21310b4db180SJacob Faibussowitsch PetscErrorCode SNESSetNGS(SNES snes, PetscErrorCode (*f)(SNES snes, Vec X, Vec B, void *ctx), void *ctx)
2132d71ae5a4SJacob Faibussowitsch {
21336cab3a1bSJed Brown   DM dm;
21346cab3a1bSJed Brown 
2135646217ecSPeter Brune   PetscFunctionBegin;
21366cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21379566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21389566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2140646217ecSPeter Brune }
2141646217ecSPeter Brune 
2142bbc1464cSBarry Smith /*
2143bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2144bbc1464cSBarry Smith    changed during the KSPSolve()
2145bbc1464cSBarry Smith */
2146d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2147d71ae5a4SJacob Faibussowitsch {
2148bbc1464cSBarry Smith   DM     dm;
2149bbc1464cSBarry Smith   DMSNES sdm;
2150bbc1464cSBarry Smith 
2151bbc1464cSBarry Smith   PetscFunctionBegin;
21529566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21539566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2154bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2155bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2156792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21579566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21580df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2159ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2160792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21619566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2162bbc1464cSBarry Smith   } else {
2163792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21649566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2165bbc1464cSBarry Smith   }
21663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2167bbc1464cSBarry Smith }
2168bbc1464cSBarry Smith 
2169d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2170d71ae5a4SJacob Faibussowitsch {
2171e03ab78fSPeter Brune   DM     dm;
2172942e3340SBarry Smith   DMSNES sdm;
21736cab3a1bSJed Brown 
21748b0a5094SBarry Smith   PetscFunctionBegin;
21759566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21769566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
21778b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2178bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2179792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21809566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2181792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
21829566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2183bbc1464cSBarry Smith   } else {
2184792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
21859566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2186bbc1464cSBarry Smith   }
21873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21888b0a5094SBarry Smith }
21898b0a5094SBarry Smith 
2190d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2191d71ae5a4SJacob Faibussowitsch {
21928b0a5094SBarry Smith   PetscFunctionBegin;
2193e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2194bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
21959566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
21969566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
21973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21988b0a5094SBarry Smith }
21998b0a5094SBarry Smith 
22008b0a5094SBarry Smith /*@C
2201f6dfbefdSBarry Smith   SNESSetPicard - Use `SNES` to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization)
22028b0a5094SBarry Smith 
2203c3339decSBarry Smith   Logically Collective
22048b0a5094SBarry Smith 
22058b0a5094SBarry Smith   Input Parameters:
2206f6dfbefdSBarry Smith + snes - the `SNES` context
2207dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
2208dc4c0fb0SBarry Smith . bp   - function evaluation routine, may be `NULL`
22096b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2210dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
221120f4b53cSBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFunction()`
2212dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2213dc4c0fb0SBarry Smith 
2214dc4c0fb0SBarry Smith   Level: intermediate
22158b0a5094SBarry Smith 
22168b0a5094SBarry Smith   Notes:
22176b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2218f450aa47SBarry 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.
2219f450aa47SBarry Smith 
2220f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22218b0a5094SBarry Smith 
2222dc4c0fb0SBarry 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}.
2223dc4c0fb0SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration.
22248b0a5094SBarry Smith 
2225dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22268b0a5094SBarry Smith 
22270d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22286b7fb656SBarry Smith   the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b
22298b0a5094SBarry Smith 
22308b0a5094SBarry 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
22318b0a5094SBarry 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
22328b0a5094SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
22338b0a5094SBarry Smith 
2234dc4c0fb0SBarry 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
2235f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
22366b7fb656SBarry Smith 
2237dc4c0fb0SBarry 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.
22386b7fb656SBarry Smith 
2239dc4c0fb0SBarry 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
22406b7fb656SBarry 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
2241f6dfbefdSBarry 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`.
2242aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2243bbc1464cSBarry Smith 
22441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, `SNESJacobianFunction`
22458b0a5094SBarry Smith @*/
2246d71ae5a4SJacob 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)
2247d71ae5a4SJacob Faibussowitsch {
2248e03ab78fSPeter Brune   DM dm;
2249e03ab78fSPeter Brune 
22508b0a5094SBarry Smith   PetscFunctionBegin;
22518b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22529566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22539566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22549566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22559566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22569566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22588b0a5094SBarry Smith }
22598b0a5094SBarry Smith 
22607971a8bfSPeter Brune /*@C
22617971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
22627971a8bfSPeter Brune 
2263f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
22647971a8bfSPeter Brune 
22657971a8bfSPeter Brune   Input Parameter:
2266f6dfbefdSBarry Smith . snes - the `SNES` context
22677971a8bfSPeter Brune 
2268d8d19677SJose E. Roman   Output Parameters:
2269dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
227020f4b53cSBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunction`
2271dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2272dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
227320f4b53cSBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFunction`
2274dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
22757971a8bfSPeter Brune 
22767971a8bfSPeter Brune   Level: advanced
22777971a8bfSPeter Brune 
22781cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunction`, `SNESJacobianFunction`
22797971a8bfSPeter Brune @*/
2280d71ae5a4SJacob 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)
2281d71ae5a4SJacob Faibussowitsch {
22827971a8bfSPeter Brune   DM dm;
22837971a8bfSPeter Brune 
22847971a8bfSPeter Brune   PetscFunctionBegin;
22857971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22869566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
22879566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
22889566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22899566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
22903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22917971a8bfSPeter Brune }
22927971a8bfSPeter Brune 
2293d25893d9SBarry Smith /*@C
2294dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2295d25893d9SBarry Smith 
2296c3339decSBarry Smith   Logically Collective
2297d25893d9SBarry Smith 
2298d25893d9SBarry Smith   Input Parameters:
2299f6dfbefdSBarry Smith + snes - the `SNES` context
2300d25893d9SBarry Smith . func - function evaluation routine
2301d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2302dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2303d25893d9SBarry Smith 
230420f4b53cSBarry Smith   Calling sequence of `func`:
230520f4b53cSBarry Smith $    PetscErrorCode func(SNES snes, Vec x, void *ctx);
230620f4b53cSBarry Smith + snes - the `SNES` solver
230720f4b53cSBarry Smith . x    - vector to put initial guess
2308d25893d9SBarry Smith - ctx  - optional user-defined function context
2309d25893d9SBarry Smith 
2310d25893d9SBarry Smith   Level: intermediate
2311d25893d9SBarry Smith 
23121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`
2313d25893d9SBarry Smith @*/
23140b4db180SJacob Faibussowitsch PetscErrorCode SNESSetComputeInitialGuess(SNES snes, PetscErrorCode (*func)(SNES snes, Vec x, void *ctx), void *ctx)
2315d71ae5a4SJacob Faibussowitsch {
2316d25893d9SBarry Smith   PetscFunctionBegin;
2317d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2318d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2319d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2321d25893d9SBarry Smith }
2322d25893d9SBarry Smith 
23231096aae1SMatthew Knepley /*@C
2324dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
23251096aae1SMatthew Knepley   it assumes a zero right hand side.
23261096aae1SMatthew Knepley 
2327c3339decSBarry Smith   Logically Collective
23281096aae1SMatthew Knepley 
23291096aae1SMatthew Knepley   Input Parameter:
2330f6dfbefdSBarry Smith . snes - the `SNES` context
23311096aae1SMatthew Knepley 
23321096aae1SMatthew Knepley   Output Parameter:
2333dc4c0fb0SBarry Smith . rhs - the right hand side vector or `NULL` if the right hand side vector is null
23341096aae1SMatthew Knepley 
23351096aae1SMatthew Knepley   Level: intermediate
23361096aae1SMatthew Knepley 
23371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23381096aae1SMatthew Knepley @*/
2339d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2340d71ae5a4SJacob Faibussowitsch {
23411096aae1SMatthew Knepley   PetscFunctionBegin;
23420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23431096aae1SMatthew Knepley   PetscValidPointer(rhs, 2);
234485385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23461096aae1SMatthew Knepley }
23471096aae1SMatthew Knepley 
23489b94acceSBarry Smith /*@
2349f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23509b94acceSBarry Smith 
2351c3339decSBarry Smith   Collective
2352c7afd0dbSLois Curfman McInnes 
23539b94acceSBarry Smith   Input Parameters:
2354f6dfbefdSBarry Smith + snes - the `SNES` context
2355c7afd0dbSLois Curfman McInnes - x    - input vector
23569b94acceSBarry Smith 
23579b94acceSBarry Smith   Output Parameter:
2358f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
23599b94acceSBarry Smith 
2360dc4c0fb0SBarry Smith   Level: developer
2361dc4c0fb0SBarry Smith 
2362f6dfbefdSBarry Smith   Note:
2363f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2364bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
236536851e7fSLois Curfman McInnes 
23661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
23679b94acceSBarry Smith @*/
2368d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2369d71ae5a4SJacob Faibussowitsch {
23706cab3a1bSJed Brown   DM     dm;
2371942e3340SBarry Smith   DMSNES sdm;
23729b94acceSBarry Smith 
23733a40ed3dSBarry Smith   PetscFunctionBegin;
23740700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23750700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
23760700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2377c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2378c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2379e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2380184914b5SBarry Smith 
23819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23829566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
23830fdf79fbSJacob 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().");
238432f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
238548a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
23869566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
23878ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
23888ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2389800f99ffSJeremy L Thompson     {
2390800f99ffSJeremy L Thompson       void *ctx;
2391800f99ffSJeremy L Thompson       PetscErrorCode (*computefunction)(SNES, Vec, Vec, void *);
2392800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2393800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2394800f99ffSJeremy L Thompson     }
23959566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
239648a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
23970fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
23989566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
23990fdf79fbSJacob Faibussowitsch   }
24001baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2401ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2402422a814eSBarry Smith   /*
2403422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2404422a814eSBarry Smith      propagate the value to all processes
2405422a814eSBarry Smith   */
24061baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24089b94acceSBarry Smith }
24099b94acceSBarry Smith 
2410c79ef259SPeter Brune /*@
2411f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2412bbc1464cSBarry Smith 
2413c3339decSBarry Smith   Collective
2414bbc1464cSBarry Smith 
2415bbc1464cSBarry Smith   Input Parameters:
2416f6dfbefdSBarry Smith + snes - the `SNES` context
2417bbc1464cSBarry Smith - x    - input vector
2418bbc1464cSBarry Smith 
2419bbc1464cSBarry Smith   Output Parameter:
2420f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2421bbc1464cSBarry Smith 
2422dc4c0fb0SBarry Smith   Level: developer
2423dc4c0fb0SBarry Smith 
2424bbc1464cSBarry Smith   Notes:
2425f6dfbefdSBarry Smith   `SNESComputeMFFunction()` is used within the matrix vector products called by the matrix created with `MatCreateSNESMF()`
2426bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2427bbc1464cSBarry Smith 
2428f6dfbefdSBarry Smith   Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with `SNESSolve()`
2429f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2430f6dfbefdSBarry 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.
2431bbc1464cSBarry Smith 
24321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2433bbc1464cSBarry Smith @*/
2434d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2435d71ae5a4SJacob Faibussowitsch {
2436bbc1464cSBarry Smith   DM     dm;
2437bbc1464cSBarry Smith   DMSNES sdm;
2438bbc1464cSBarry Smith 
2439bbc1464cSBarry Smith   PetscFunctionBegin;
2440bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2441bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2442bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2443bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2444bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2445e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2446bbc1464cSBarry Smith 
24479566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24489566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24509566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2451bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2452bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2453792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24549566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24559566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2456bbc1464cSBarry Smith   snes->nfuncs++;
2457bbc1464cSBarry Smith   /*
2458bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2459bbc1464cSBarry Smith      propagate the value to all processes
2460bbc1464cSBarry Smith   */
24611baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2463bbc1464cSBarry Smith }
2464bbc1464cSBarry Smith 
2465bbc1464cSBarry Smith /*@
2466f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with  `SNESSetNGS()`.
2467c79ef259SPeter Brune 
2468c3339decSBarry Smith   Collective
2469c79ef259SPeter Brune 
2470c79ef259SPeter Brune   Input Parameters:
2471f6dfbefdSBarry Smith + snes - the `SNES` context
2472c79ef259SPeter Brune . x    - input vector
2473c79ef259SPeter Brune - b    - rhs vector
2474c79ef259SPeter Brune 
2475c79ef259SPeter Brune   Output Parameter:
2476c79ef259SPeter Brune . x - new solution vector
2477c79ef259SPeter Brune 
2478dc4c0fb0SBarry Smith   Level: developer
2479dc4c0fb0SBarry Smith 
2480f6dfbefdSBarry Smith   Note:
2481f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2482c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2483c79ef259SPeter Brune   themselves.
2484c79ef259SPeter Brune 
24851cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESSetNGS()`, `SNESComputeFunction()`
2486c79ef259SPeter Brune @*/
2487d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2488d71ae5a4SJacob Faibussowitsch {
24896cab3a1bSJed Brown   DM     dm;
2490942e3340SBarry Smith   DMSNES sdm;
2491646217ecSPeter Brune 
2492646217ecSPeter Brune   PetscFunctionBegin;
2493646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2494064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2495064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2496064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2497064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2498e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
24999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25009566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25019566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25020fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25039566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2504792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25059566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2508646217ecSPeter Brune }
2509646217ecSPeter Brune 
2510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2511d71ae5a4SJacob Faibussowitsch {
251212837594SBarry Smith   Mat               A, B, C, D, jacobian;
2513e885f1abSBarry Smith   Vec               x = snes->vec_sol, f = snes->vec_func;
2514e885f1abSBarry Smith   PetscReal         nrm, gnorm;
251581e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
25160e276705SLisandro Dalcin   MatType           mattype;
2517e885f1abSBarry Smith   PetscInt          m, n, M, N;
2518e885f1abSBarry Smith   void             *functx;
25192cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
25203325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2521e885f1abSBarry Smith   MPI_Comm          comm;
2522e885f1abSBarry Smith   PetscInt          tabs;
252312837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
25243325ff46SBarry Smith   PetscViewerFormat format;
2525e885f1abSBarry Smith 
2526e885f1abSBarry Smith   PetscFunctionBegin;
2527d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
25289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
25299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
25309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
25314ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
25329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
25334ead3382SBarry 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 */
25349566063dSJacob 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));
2535d0609cedSBarry Smith   PetscOptionsEnd();
25363ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2537e885f1abSBarry Smith 
25389566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
25399566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
25409566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
25419566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
25429566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
254312837594SBarry Smith   if (!complete_print && !directionsprinted) {
25449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
25459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
254612837594SBarry Smith   }
254712837594SBarry Smith   if (!directionsprinted) {
25489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
25499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
255012837594SBarry Smith     directionsprinted = PETSC_TRUE;
2551e885f1abSBarry Smith   }
25521baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2553e885f1abSBarry Smith 
25549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
255512837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
255612837594SBarry Smith   else jacobian = snes->jacobian_pre;
255712837594SBarry Smith 
2558a82339d0SMatthew G. Knepley   if (!x) {
25599566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(jacobian, &x, NULL));
2560a82339d0SMatthew G. Knepley   } else {
25619566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
2562a82339d0SMatthew G. Knepley   }
2563a82339d0SMatthew G. Knepley   if (!f) {
25649566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &f));
2565a82339d0SMatthew G. Knepley   } else {
25669566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)f));
2567a82339d0SMatthew G. Knepley   }
2568a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
25699566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
25709566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
25719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
257212837594SBarry Smith   while (jacobian) {
25732cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
25742cd624f9SStefano Zampini 
25752cd624f9SStefano Zampini     if (istranspose) {
25769566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
25772cd624f9SStefano Zampini       Jsave    = jacobian;
25782cd624f9SStefano Zampini       jacobian = JT;
25792cd624f9SStefano Zampini     }
25809566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
258112837594SBarry Smith     if (flg) {
258212837594SBarry Smith       A = jacobian;
25839566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
258412837594SBarry Smith     } else {
25859566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
258612837594SBarry Smith     }
2587e885f1abSBarry Smith 
25889566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
25899566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
25909566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
25919566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
25929566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
25939566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
25949566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
25959566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
25969566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2597e885f1abSBarry Smith 
25989566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
25999566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
260012837594SBarry Smith 
26019566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
26029566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26039566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
26049566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
26059566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
260612837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
26079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
260812837594SBarry Smith 
2609e885f1abSBarry Smith     if (complete_print) {
26109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
26119566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
26129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
26139566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2614e885f1abSBarry Smith     }
2615e885f1abSBarry Smith 
2616df10fb39SFande Kong     if (threshold_print || complete_print) {
2617e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2618e885f1abSBarry Smith       PetscScalar       *cvals;
2619e885f1abSBarry Smith       const PetscInt    *bcols;
2620e885f1abSBarry Smith       const PetscScalar *bvals;
2621e885f1abSBarry Smith 
26229566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
26239566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
26249566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
26259566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
26269566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
26279566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
26280e276705SLisandro Dalcin 
26299566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26309566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2631e885f1abSBarry Smith 
2632e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
26339566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
26349566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2635e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
263623a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2637e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2638e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2639e885f1abSBarry Smith             cncols += 1;
2640e885f1abSBarry Smith           }
2641e885f1abSBarry Smith         }
264248a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
26439566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
26449566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2645e885f1abSBarry Smith       }
26469566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
26479566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
26489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
26499566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
26509566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2651e885f1abSBarry Smith     }
26529566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
26539566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
26549566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
26552cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
265612837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
265712837594SBarry Smith       jacobian = snes->jacobian_pre;
26589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
26599371c9d4SSatish Balay     } else jacobian = NULL;
266012837594SBarry Smith   }
26619566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
26621baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
26639566063dSJacob Faibussowitsch   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
26649566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
26653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2666e885f1abSBarry Smith }
2667e885f1abSBarry Smith 
266862fef451SLois Curfman McInnes /*@
2669f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
267062fef451SLois Curfman McInnes 
2671c3339decSBarry Smith   Collective
2672c7afd0dbSLois Curfman McInnes 
267362fef451SLois Curfman McInnes   Input Parameters:
2674f6dfbefdSBarry Smith + snes - the `SNES` context
2675e4094ef1SJacob Faibussowitsch - X    - input vector
267662fef451SLois Curfman McInnes 
267762fef451SLois Curfman McInnes   Output Parameters:
2678c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2679f6dfbefdSBarry Smith - B - optional matrix for building the preconditioner
2680fee21e36SBarry Smith 
2681e35cf81dSBarry Smith   Options Database Keys:
268267b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
268367b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2684455a5933SJed 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.
2685455a5933SJed 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
2686693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2687693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2688693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
26894c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
269094d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2691a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2692c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2693dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2694dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2695a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2696a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2697c01495d3SJed Brown 
2698dc4c0fb0SBarry Smith   Level: developer
2699dc4c0fb0SBarry Smith 
2700f6dfbefdSBarry Smith   Note:
270162fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
270262fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
270362fef451SLois Curfman McInnes 
2704e4094ef1SJacob Faibussowitsch   Developer Notes:
2705dc4c0fb0SBarry 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
2706dc4c0fb0SBarry Smith   for with the `SNESType` of test that has been removed.
2707e885f1abSBarry Smith 
27081cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
270962fef451SLois Curfman McInnes @*/
2710d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2711d71ae5a4SJacob Faibussowitsch {
2712ace3abfcSBarry Smith   PetscBool flag;
27136cab3a1bSJed Brown   DM        dm;
2714942e3340SBarry Smith   DMSNES    sdm;
2715e0e3a89bSBarry Smith   KSP       ksp;
27163a40ed3dSBarry Smith 
27173a40ed3dSBarry Smith   PetscFunctionBegin;
27180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
27190700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2720c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2721e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
27229566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
27239566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
27243232da50SPeter Brune 
2725ebd3b9afSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
2726fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2727fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2728f5af7f23SKarl Rupp 
27299566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2730fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
27319566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
27329566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2733ebd3b9afSBarry Smith     if (flag) {
27349566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27359566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2736ebd3b9afSBarry Smith     }
27373ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
273837ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
273963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
27409566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2741ebd3b9afSBarry Smith     if (flag) {
27429566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27439566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2744ebd3b9afSBarry Smith     }
27453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2746e35cf81dSBarry Smith   }
2747efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
27489566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27499566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
27503ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2751d728fb7dSPeter Brune   }
2752e35cf81dSBarry Smith 
27539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
27549566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2755800f99ffSJeremy L Thompson   {
2756800f99ffSJeremy L Thompson     void *ctx;
2757800f99ffSJeremy L Thompson     PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *);
2758800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2759800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2760800f99ffSJeremy L Thompson   }
27619566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
27629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
276328d58a37SPierre Jolivet 
276428d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
27659566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2766a8054027SBarry Smith 
2767e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
27689566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
27693b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
27709566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
27719566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
27723b4f5425SBarry Smith     snes->lagpreconditioner = -1;
27733b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
27749566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
27759566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
277637ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
277763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
27789566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2779d1e9a80fSBarry Smith   } else {
27809566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
27819566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2782a8054027SBarry Smith   }
2783a8054027SBarry Smith 
27849566063dSJacob Faibussowitsch   PetscCall(SNESTestJacobian(snes));
27856d84be18SBarry Smith   /* make sure user returned a correct Jacobian and preconditioner */
278694ab13aaSBarry Smith   /* PetscValidHeaderSpecific(A,MAT_CLASSID,3);
278794ab13aaSBarry Smith     PetscValidHeaderSpecific(B,MAT_CLASSID,4);   */
2788693365a8SJed Brown   {
2789693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
27909566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
27919566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
27929566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
27939566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2794693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
27950298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2796693365a8SJed Brown       PetscViewer vdraw, vstdout;
27976b3a5b13SJed Brown       PetscBool   flg;
2798693365a8SJed Brown       if (flag_operator) {
27999566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2800693365a8SJed Brown         Bexp = Bexp_mine;
2801693365a8SJed Brown       } else {
2802693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
28039566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
280494ab13aaSBarry Smith         if (flg) Bexp = B;
2805693365a8SJed Brown         else {
2806693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
28079566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2808693365a8SJed Brown           Bexp = Bexp_mine;
2809693365a8SJed Brown         }
2810693365a8SJed Brown       }
28119566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
28129566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
28139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2814693365a8SJed Brown       if (flag_draw || flag_contour) {
28159566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28169566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28170298fd71SBarry Smith       } else vdraw = NULL;
28189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
28199566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
28209566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
28219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
28229566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
28239566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
28249566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
28259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
28269566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2827693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
28289566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28299566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
28309566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2831693365a8SJed Brown       }
28329566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
28339566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
28349566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
28359566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2836693365a8SJed Brown     }
2837693365a8SJed Brown   }
28384c30e9fbSJed Brown   {
28396719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
28406719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
28419566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
28429566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
28439566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
28449566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
28459566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
284627b0f280SBarry Smith     if (flag_threshold) {
28479566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
28489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
284927b0f280SBarry Smith     }
28506719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
28514c30e9fbSJed Brown       Mat           Bfd;
28524c30e9fbSJed Brown       PetscViewer   vdraw, vstdout;
2853335efc43SPeter Brune       MatColoring   coloring;
28544c30e9fbSJed Brown       ISColoring    iscoloring;
28554c30e9fbSJed Brown       MatFDColoring matfdcoloring;
28564c30e9fbSJed Brown       PetscErrorCode (*func)(SNES, Vec, Vec, void *);
28574c30e9fbSJed Brown       void     *funcctx;
28586719d8e4SJed Brown       PetscReal norm1, norm2, normmax;
28594c30e9fbSJed Brown 
28609566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
28619566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
28629566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
28639566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
28649566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
28659566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
28669566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
28679566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28689566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
28699566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
28704c30e9fbSJed Brown 
28714c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
28729566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
28739566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
28749566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
28759566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
28769566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28779566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
28789566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
28794c30e9fbSJed Brown 
28809566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
28814c30e9fbSJed Brown       if (flag_draw || flag_contour) {
28829566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28839566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28840298fd71SBarry Smith       } else vdraw = NULL;
28859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
28869566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
28879566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
28889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
28899566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
28909566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
28919566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
28929566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
28939566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
28949566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
28959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
28969566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
28974c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
28989566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28999566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
29009566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
29014c30e9fbSJed Brown       }
29029566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29036719d8e4SJed Brown 
29046719d8e4SJed Brown       if (flag_threshold) {
29056719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
29069566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
29079566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
29086719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
29096719d8e4SJed Brown           const PetscScalar *ba, *ca;
29106719d8e4SJed Brown           const PetscInt    *bj, *cj;
29116719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
29126719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
29139566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
29149566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
29155f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
29166719d8e4SJed Brown           for (j = 0; j < bn; j++) {
29176719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
29186719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
29196719d8e4SJed Brown               maxentrycol = bj[j];
29206719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
29216719d8e4SJed Brown             }
29226719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
29236719d8e4SJed Brown               maxdiffcol = bj[j];
29246719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
29256719d8e4SJed Brown             }
29266719d8e4SJed Brown             if (rdiff > maxrdiff) {
29276719d8e4SJed Brown               maxrdiffcol = bj[j];
29286719d8e4SJed Brown               maxrdiff    = rdiff;
29296719d8e4SJed Brown             }
29306719d8e4SJed Brown           }
29316719d8e4SJed Brown           if (maxrdiff > 1) {
293263a3b9bcSJacob 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));
29336719d8e4SJed Brown             for (j = 0; j < bn; j++) {
29346719d8e4SJed Brown               PetscReal rdiff;
29356719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
293648a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
29376719d8e4SJed Brown             }
293863a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
29396719d8e4SJed Brown           }
29409566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
29419566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
29426719d8e4SJed Brown         }
29436719d8e4SJed Brown       }
29449566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29459566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
29464c30e9fbSJed Brown     }
29474c30e9fbSJed Brown   }
29483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29499b94acceSBarry Smith }
29509b94acceSBarry Smith 
2951bf388a1fSBarry Smith /*MC
2952f6dfbefdSBarry Smith     SNESJacobianFunction - Function used by `SNES` to compute the nonlinear Jacobian of the function to be solved by `SNES`
2953bf388a1fSBarry Smith 
2954bf388a1fSBarry Smith      Synopsis:
2955411c0326SBarry Smith      #include "petscsnes.h"
2956411c0326SBarry Smith      PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
2957bf388a1fSBarry Smith 
2958c3339decSBarry Smith      Collective
29591843f636SBarry Smith 
29601843f636SBarry Smith     Input Parameters:
29611843f636SBarry Smith +  x - input vector, the Jacobian is to be computed at this value
2962bf388a1fSBarry Smith -  ctx - [optional] user-defined Jacobian context
2963bf388a1fSBarry Smith 
29641843f636SBarry Smith     Output Parameters:
29651843f636SBarry Smith +  Amat - the matrix that defines the (approximate) Jacobian
2966dc4c0fb0SBarry Smith -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
29671843f636SBarry Smith 
2968878cb397SSatish Balay    Level: intermediate
2969878cb397SSatish Balay 
29701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESSetJacobian()`, `SNESGetJacobian()`
2971bf388a1fSBarry Smith M*/
2972bf388a1fSBarry Smith 
29739b94acceSBarry Smith /*@C
29749b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
2975044dda88SLois Curfman McInnes   location to store the matrix.
29769b94acceSBarry Smith 
2977c3339decSBarry Smith   Logically Collective
2978c7afd0dbSLois Curfman McInnes 
29799b94acceSBarry Smith   Input Parameters:
2980f6dfbefdSBarry Smith + snes - the `SNES` context
2981e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
2982dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
2983dc4c0fb0SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFunction` for details
2984c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
2985dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
2986dc4c0fb0SBarry Smith 
2987dc4c0fb0SBarry Smith   Level: beginner
29889b94acceSBarry Smith 
29899b94acceSBarry Smith   Notes:
2990dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
299116913363SBarry Smith   each matrix.
299216913363SBarry Smith 
2993dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
2994dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
2995895c21f2SBarry Smith 
2996dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
2997f6dfbefdSBarry Smith   must be a `MatFDColoring`.
2998a8a26c1eSJed Brown 
2999c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3000f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3001c3cc8fd1SJed Brown 
30021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
3003db781477SPatrick Sanan           `SNESSetPicard()`, `SNESJacobianFunction`
30049b94acceSBarry Smith @*/
3005d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx)
3006d71ae5a4SJacob Faibussowitsch {
30076cab3a1bSJed Brown   DM dm;
30083a7fca6bSBarry Smith 
30093a40ed3dSBarry Smith   PetscFunctionBegin;
30100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3011e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3012e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3013e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3014e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
30159566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30169566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3017e5d3d808SBarry Smith   if (Amat) {
30189566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
30199566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3020f5af7f23SKarl Rupp 
3021e5d3d808SBarry Smith     snes->jacobian = Amat;
30223a7fca6bSBarry Smith   }
3023e5d3d808SBarry Smith   if (Pmat) {
30249566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
30259566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3026f5af7f23SKarl Rupp 
3027e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
30283a7fca6bSBarry Smith   }
30293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30309b94acceSBarry Smith }
303162fef451SLois Curfman McInnes 
3032c2aafc4cSSatish Balay /*@C
3033b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3034b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3035b4fd4287SBarry Smith 
3036f6dfbefdSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` object is
3037c7afd0dbSLois Curfman McInnes 
3038b4fd4287SBarry Smith   Input Parameter:
3039b4fd4287SBarry Smith . snes - the nonlinear solver context
3040b4fd4287SBarry Smith 
3041b4fd4287SBarry Smith   Output Parameters:
3042dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3043dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
304420f4b53cSBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFunction`
3045dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3046fee21e36SBarry Smith 
304736851e7fSLois Curfman McInnes   Level: advanced
304836851e7fSLois Curfman McInnes 
30491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFunction`, `SNESGetFunction()`
3050b4fd4287SBarry Smith @*/
3051d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx)
3052d71ae5a4SJacob Faibussowitsch {
30536cab3a1bSJed Brown   DM dm;
30546cab3a1bSJed Brown 
30553a40ed3dSBarry Smith   PetscFunctionBegin;
30560700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3057e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3058e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
30599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3060800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
30613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3062b4fd4287SBarry Smith }
3063b4fd4287SBarry Smith 
3064d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3065d71ae5a4SJacob Faibussowitsch {
306658b371f3SBarry Smith   DM     dm;
306758b371f3SBarry Smith   DMSNES sdm;
306858b371f3SBarry Smith 
306958b371f3SBarry Smith   PetscFunctionBegin;
30709566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30719566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
307258b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
307358b371f3SBarry Smith     DM        dm;
307458b371f3SBarry Smith     PetscBool isdense, ismf;
307558b371f3SBarry Smith 
30769566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
30779566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
30789566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
307958b371f3SBarry Smith     if (isdense) {
30809566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
308158b371f3SBarry Smith     } else if (!ismf) {
30829566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
308358b371f3SBarry Smith     }
308458b371f3SBarry Smith   }
30853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308658b371f3SBarry Smith }
308758b371f3SBarry Smith 
30889b94acceSBarry Smith /*@
30899b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3090272ac6f2SLois Curfman McInnes   of a nonlinear solver.
30919b94acceSBarry Smith 
3092c3339decSBarry Smith   Collective
3093fee21e36SBarry Smith 
30942fe279fdSBarry Smith   Input Parameter:
3095f6dfbefdSBarry Smith . snes - the `SNES` context
3096c7afd0dbSLois Curfman McInnes 
3097dc4c0fb0SBarry Smith   Level: advanced
3098dc4c0fb0SBarry Smith 
3099f6dfbefdSBarry Smith   Note:
3100f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3101f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3102f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3103f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3104f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3105272ac6f2SLois Curfman McInnes 
31061cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
31079b94acceSBarry Smith @*/
3108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3109d71ae5a4SJacob Faibussowitsch {
31106cab3a1bSJed Brown   DM             dm;
3111942e3340SBarry Smith   DMSNES         sdm;
3112c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
31136e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
31149b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
31159b5c1c08SStefano Zampini   Vec            f, fpc;
31169b5c1c08SStefano Zampini   void          *funcctx;
31179b5c1c08SStefano Zampini   void          *jacctx, *appctx;
31189b5c1c08SStefano Zampini   Mat            j, jpre;
31196b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
31206b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
31216e2a1849SPeter Brune   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
3122d1e9a80fSBarry Smith   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
31233a40ed3dSBarry Smith 
31243a40ed3dSBarry Smith   PetscFunctionBegin;
31250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31263ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3127fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
31289b94acceSBarry Smith 
312948a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
313085385478SLisandro Dalcin 
31319566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
313258c9b817SLisandro Dalcin 
31339566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31349566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
31359566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
313658b371f3SBarry Smith 
313748a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3138efd51863SBarry Smith 
313948a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3140b710008aSBarry Smith 
3141d8d34be6SBarry Smith   if (snes->linesearch) {
31429566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
31439566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3144d8d34be6SBarry Smith   }
31459e764e56SPeter Brune 
31469b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3147b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3148172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3149172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3150172a4300SPeter Brune   }
3151d8f46077SPeter Brune 
3152efd4aadfSBarry Smith   if (snes->npc) {
31536e2a1849SPeter Brune     /* copy the DM over */
31549566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31559566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
31566e2a1849SPeter Brune 
31579566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
31589566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
31599566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
31609566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
31619566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
31629566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
31639566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
31649b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
31659566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
31666e2a1849SPeter Brune 
31676e2a1849SPeter Brune     /* copy the function pointers over */
31689566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
31696e2a1849SPeter Brune 
31706e2a1849SPeter Brune     /* default to 1 iteration */
31719566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3172efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
31739566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3174a9936a0cSPeter Brune     } else {
31759566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3176a9936a0cSPeter Brune     }
31779566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
31786e2a1849SPeter Brune 
31796e2a1849SPeter Brune     /* copy the line search context over */
3180d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
31819566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
31829566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
31839566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
31849566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
31859566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
31869566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
31879566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
31886e2a1849SPeter Brune     }
3189d8d34be6SBarry Smith   }
31901baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
319148a46eb9SPierre Jolivet   if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user));
31926e2a1849SPeter Brune 
319337ec4e1aSPeter Brune   snes->jac_iter = 0;
319437ec4e1aSPeter Brune   snes->pre_iter = 0;
319537ec4e1aSPeter Brune 
3196dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
319758c9b817SLisandro Dalcin 
31989566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
319958b371f3SBarry Smith 
3200b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
32016c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3202d8d34be6SBarry Smith       if (snes->linesearch) {
32039566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
32049566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
32056c67d002SPeter Brune       }
32066c67d002SPeter Brune     }
3207d8d34be6SBarry Smith   }
3208fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
32097aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
32103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32119b94acceSBarry Smith }
32129b94acceSBarry Smith 
321337596af1SLisandro Dalcin /*@
3214f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
321537596af1SLisandro Dalcin 
3216c3339decSBarry Smith   Collective
321737596af1SLisandro Dalcin 
321837596af1SLisandro Dalcin   Input Parameter:
3219f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
322037596af1SLisandro Dalcin 
3221d25893d9SBarry Smith   Level: intermediate
3222d25893d9SBarry Smith 
322395452b02SPatrick Sanan   Notes:
3224f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
322537596af1SLisandro Dalcin 
3226f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3227f6dfbefdSBarry Smith 
32281cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
322937596af1SLisandro Dalcin @*/
3230d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3231d71ae5a4SJacob Faibussowitsch {
323237596af1SLisandro Dalcin   PetscFunctionBegin;
323337596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3234d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
32359566063dSJacob Faibussowitsch     PetscCall((*snes->ops->userdestroy)((void **)&snes->user));
32360298fd71SBarry Smith     snes->user = NULL;
3237d25893d9SBarry Smith   }
32381baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
32398a23116dSBarry Smith 
3240dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
32411baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
32429e764e56SPeter Brune 
32431baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
32449e764e56SPeter Brune 
32459566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
32469566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
32479566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
32489566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
32499566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
32509566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
32519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
32529566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
32539566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3254f5af7f23SKarl Rupp 
325540fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
325640fdac6aSLawrence Mitchell 
325737596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
325837596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
32593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
326037596af1SLisandro Dalcin }
326137596af1SLisandro Dalcin 
326252baeb72SSatish Balay /*@
3263f6dfbefdSBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object.
3264c4421ceaSFande Kong 
3265c3339decSBarry Smith   Collective
3266c4421ceaSFande Kong 
3267c4421ceaSFande Kong   Input Parameter:
3268f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3269c4421ceaSFande Kong 
3270c4421ceaSFande Kong   Level: intermediate
3271c4421ceaSFande Kong 
32721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`
3273c4421ceaSFande Kong @*/
3274d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3275d71ae5a4SJacob Faibussowitsch {
3276c4421ceaSFande Kong   PetscInt i;
3277c4421ceaSFande Kong 
3278c4421ceaSFande Kong   PetscFunctionBegin;
3279c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3280c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
328148a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3282c4421ceaSFande Kong   }
3283c4421ceaSFande Kong   snes->numberreasonviews = 0;
32843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3285c4421ceaSFande Kong }
3286c4421ceaSFande Kong 
32871fb7b255SJunchao Zhang /*@C
32889b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3289f6dfbefdSBarry Smith   with `SNESCreate()`.
32909b94acceSBarry Smith 
3291c3339decSBarry Smith   Collective
3292c7afd0dbSLois Curfman McInnes 
32939b94acceSBarry Smith   Input Parameter:
3294f6dfbefdSBarry Smith . snes - the `SNES` context
32959b94acceSBarry Smith 
329636851e7fSLois Curfman McInnes   Level: beginner
329736851e7fSLois Curfman McInnes 
32981cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
32999b94acceSBarry Smith @*/
3300d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3301d71ae5a4SJacob Faibussowitsch {
33023a40ed3dSBarry Smith   PetscFunctionBegin;
33033ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
33046bf464f9SBarry Smith   PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1);
33059371c9d4SSatish Balay   if (--((PetscObject)(*snes))->refct > 0) {
33069371c9d4SSatish Balay     *snes = NULL;
33073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
33089371c9d4SSatish Balay   }
3309d4bb536fSBarry Smith 
33109566063dSJacob Faibussowitsch   PetscCall(SNESReset((*snes)));
33119566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
33126b8b9a38SLisandro Dalcin 
3313e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
33149566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3315dbbe0bcdSBarry Smith   PetscTryTypeMethod((*snes), destroy);
33166d4c513bSLisandro Dalcin 
33179566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
33189566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
33199566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
33209566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
33216b8b9a38SLisandro Dalcin 
33229566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
332348a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
332448a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
33259566063dSJacob Faibussowitsch   PetscCall(SNESMonitorCancel((*snes)));
33269566063dSJacob Faibussowitsch   PetscCall(SNESConvergedReasonViewCancel((*snes)));
33279566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
33283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33299b94acceSBarry Smith }
33309b94acceSBarry Smith 
33319b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
33329b94acceSBarry Smith 
3333a8054027SBarry Smith /*@
3334a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3335a8054027SBarry Smith 
3336c3339decSBarry Smith   Logically Collective
3337a8054027SBarry Smith 
3338a8054027SBarry Smith   Input Parameters:
3339f6dfbefdSBarry Smith + snes - the `SNES` context
3340d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
33413b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3342a8054027SBarry Smith 
3343a8054027SBarry Smith   Options Database Keys:
334479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
33453d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
334679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
33473d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3348a8054027SBarry Smith 
3349a8054027SBarry Smith   Notes:
3350e4094ef1SJacob Faibussowitsch 
3351dc4c0fb0SBarry Smith   Level: intermediate
3352dc4c0fb0SBarry Smith 
3353a8054027SBarry Smith    The default is 1
3354f6dfbefdSBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3355d8e291bfSBarry Smith 
3356f6dfbefdSBarry Smith    `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3357a8054027SBarry Smith 
33581cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3359f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3360a8054027SBarry Smith @*/
3361d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3362d71ae5a4SJacob Faibussowitsch {
3363a8054027SBarry Smith   PetscFunctionBegin;
33640700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33655f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
33665f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3367c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3368a8054027SBarry Smith   snes->lagpreconditioner = lag;
33693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3370a8054027SBarry Smith }
3371a8054027SBarry Smith 
3372efd51863SBarry Smith /*@
3373f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3374efd51863SBarry Smith 
3375c3339decSBarry Smith   Logically Collective
3376efd51863SBarry Smith 
3377efd51863SBarry Smith   Input Parameters:
3378f6dfbefdSBarry Smith + snes  - the `SNES` context
3379efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3380efd51863SBarry Smith 
3381f6dfbefdSBarry Smith   Options Database Key:
338267b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3383efd51863SBarry Smith 
3384efd51863SBarry Smith   Level: intermediate
3385efd51863SBarry Smith 
3386f6dfbefdSBarry Smith   Note:
3387f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3388c0df2a02SJed Brown 
33891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`
3390efd51863SBarry Smith @*/
3391d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3392d71ae5a4SJacob Faibussowitsch {
3393efd51863SBarry Smith   PetscFunctionBegin;
3394efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3395efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3396efd51863SBarry Smith   snes->gridsequence = steps;
33973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3398efd51863SBarry Smith }
3399efd51863SBarry Smith 
3400fa19ca70SBarry Smith /*@
3401f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3402fa19ca70SBarry Smith 
3403c3339decSBarry Smith   Logically Collective
3404fa19ca70SBarry Smith 
3405fa19ca70SBarry Smith   Input Parameter:
3406f6dfbefdSBarry Smith . snes - the `SNES` context
3407fa19ca70SBarry Smith 
3408fa19ca70SBarry Smith   Output Parameter:
3409fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3410fa19ca70SBarry Smith 
3411f6dfbefdSBarry Smith   Options Database Key:
341267b8a455SSatish Balay . -snes_grid_sequence <steps> - set number of refinements
3413fa19ca70SBarry Smith 
3414fa19ca70SBarry Smith   Level: intermediate
3415fa19ca70SBarry Smith 
3416f6dfbefdSBarry Smith   Note:
3417f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3418fa19ca70SBarry Smith 
34191cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3420fa19ca70SBarry Smith @*/
3421d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3422d71ae5a4SJacob Faibussowitsch {
3423fa19ca70SBarry Smith   PetscFunctionBegin;
3424fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3425fa19ca70SBarry Smith   *steps = snes->gridsequence;
34263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3427fa19ca70SBarry Smith }
3428fa19ca70SBarry Smith 
3429a8054027SBarry Smith /*@
3430f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3431a8054027SBarry Smith 
34323f9fe445SBarry Smith   Not Collective
3433a8054027SBarry Smith 
3434a8054027SBarry Smith   Input Parameter:
3435f6dfbefdSBarry Smith . snes - the `SNES` context
3436a8054027SBarry Smith 
3437a8054027SBarry Smith   Output Parameter:
3438a8054027SBarry 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
34393b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3440a8054027SBarry Smith 
3441a8054027SBarry Smith   Options Database Keys:
344279a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
34433d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
344479a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
34453d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3446a8054027SBarry Smith 
3447dc4c0fb0SBarry Smith   Level: intermediate
3448dc4c0fb0SBarry Smith 
3449a8054027SBarry Smith   Notes:
3450a8054027SBarry Smith   The default is 1
3451f6dfbefdSBarry Smith 
3452a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3453a8054027SBarry Smith 
34541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3455a8054027SBarry Smith @*/
3456d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3457d71ae5a4SJacob Faibussowitsch {
3458a8054027SBarry Smith   PetscFunctionBegin;
34590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3460a8054027SBarry Smith   *lag = snes->lagpreconditioner;
34613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3462a8054027SBarry Smith }
3463a8054027SBarry Smith 
3464e35cf81dSBarry Smith /*@
3465f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3466e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3467e35cf81dSBarry Smith 
3468c3339decSBarry Smith   Logically Collective
3469e35cf81dSBarry Smith 
3470e35cf81dSBarry Smith   Input Parameters:
3471f6dfbefdSBarry Smith + snes - the `SNES` context
3472e35cf81dSBarry 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
3473fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3474e35cf81dSBarry Smith 
3475e35cf81dSBarry Smith   Options Database Keys:
347679a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
34773d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
347879a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
34793d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3480e35cf81dSBarry Smith 
3481dc4c0fb0SBarry Smith   Level: intermediate
3482dc4c0fb0SBarry Smith 
3483e35cf81dSBarry Smith   Notes:
3484e35cf81dSBarry Smith   The default is 1
3485f6dfbefdSBarry Smith 
3486e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3487f6dfbefdSBarry Smith 
3488fe3ffe1eSBarry 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
3489fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3490e35cf81dSBarry Smith 
34911cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3492e35cf81dSBarry Smith @*/
3493d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3494d71ae5a4SJacob Faibussowitsch {
3495e35cf81dSBarry Smith   PetscFunctionBegin;
34960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34975f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
34985f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3499c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3500e35cf81dSBarry Smith   snes->lagjacobian = lag;
35013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3502e35cf81dSBarry Smith }
3503e35cf81dSBarry Smith 
3504e35cf81dSBarry Smith /*@
3505f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3506e35cf81dSBarry Smith 
35073f9fe445SBarry Smith   Not Collective
3508e35cf81dSBarry Smith 
3509e35cf81dSBarry Smith   Input Parameter:
3510f6dfbefdSBarry Smith . snes - the `SNES` context
3511e35cf81dSBarry Smith 
3512e35cf81dSBarry Smith   Output Parameter:
3513e35cf81dSBarry 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
3514e35cf81dSBarry Smith          the Jacobian is built etc.
3515e35cf81dSBarry Smith 
3516dc4c0fb0SBarry Smith   Level: intermediate
3517dc4c0fb0SBarry Smith 
3518e35cf81dSBarry Smith   Notes:
3519e35cf81dSBarry Smith   The default is 1
3520f6dfbefdSBarry Smith 
3521f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3522e35cf81dSBarry Smith 
35231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3524e35cf81dSBarry Smith 
3525e35cf81dSBarry Smith @*/
3526d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3527d71ae5a4SJacob Faibussowitsch {
3528e35cf81dSBarry Smith   PetscFunctionBegin;
35290700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3530e35cf81dSBarry Smith   *lag = snes->lagjacobian;
35313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3532e35cf81dSBarry Smith }
3533e35cf81dSBarry Smith 
353437ec4e1aSPeter Brune /*@
3535f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
353637ec4e1aSPeter Brune 
3537c3339decSBarry Smith   Logically collective
353837ec4e1aSPeter Brune 
3539d8d19677SJose E. Roman   Input Parameters:
3540f6dfbefdSBarry Smith + snes - the `SNES` context
35419d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
354237ec4e1aSPeter Brune 
354337ec4e1aSPeter Brune   Options Database Keys:
354479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35453d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
354679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35473d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
35483d5a8a6aSBarry Smith 
3549dc4c0fb0SBarry Smith   Level: advanced
3550dc4c0fb0SBarry Smith 
355195452b02SPatrick Sanan   Notes:
3552f6dfbefdSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3553f6dfbefdSBarry Smith 
355495452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
355537ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
355637ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
355737ec4e1aSPeter Brune 
3558e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagJacobianPersists()`
355937ec4e1aSPeter Brune @*/
3560d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3561d71ae5a4SJacob Faibussowitsch {
356237ec4e1aSPeter Brune   PetscFunctionBegin;
356337ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
356437ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
356537ec4e1aSPeter Brune   snes->lagjac_persist = flg;
35663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
356737ec4e1aSPeter Brune }
356837ec4e1aSPeter Brune 
356937ec4e1aSPeter Brune /*@
3570d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
357137ec4e1aSPeter Brune 
3572c3339decSBarry Smith   Logically Collective
357337ec4e1aSPeter Brune 
3574d8d19677SJose E. Roman   Input Parameters:
3575f6dfbefdSBarry Smith + snes - the `SNES` context
35769d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
357737ec4e1aSPeter Brune 
357837ec4e1aSPeter Brune   Options Database Keys:
357979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35803d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
358179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35823d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
358337ec4e1aSPeter Brune 
3584dc4c0fb0SBarry Smith   Level: developer
3585dc4c0fb0SBarry Smith 
358695452b02SPatrick Sanan   Notes:
3587f6dfbefdSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3588f6dfbefdSBarry Smith 
358995452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
359037ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
359137ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
359237ec4e1aSPeter Brune 
35931cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
359437ec4e1aSPeter Brune @*/
3595d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3596d71ae5a4SJacob Faibussowitsch {
359737ec4e1aSPeter Brune   PetscFunctionBegin;
359837ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
359937ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
360037ec4e1aSPeter Brune   snes->lagpre_persist = flg;
36013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
360237ec4e1aSPeter Brune }
360337ec4e1aSPeter Brune 
36049b94acceSBarry Smith /*@
3605f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3606be5caee7SBarry Smith 
3607c3339decSBarry Smith   Logically Collective
3608be5caee7SBarry Smith 
3609be5caee7SBarry Smith   Input Parameters:
3610f6dfbefdSBarry Smith + snes  - the `SNES` context
3611f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3612be5caee7SBarry Smith 
3613f6dfbefdSBarry Smith   Options Database Key:
3614be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3615be5caee7SBarry Smith 
3616dc4c0fb0SBarry Smith   Level: intermediate
3617dc4c0fb0SBarry Smith 
3618f6dfbefdSBarry Smith   Note:
3619f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3620be5caee7SBarry Smith 
36211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3622be5caee7SBarry Smith @*/
3623d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3624d71ae5a4SJacob Faibussowitsch {
3625be5caee7SBarry Smith   PetscFunctionBegin;
3626be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3627be5caee7SBarry Smith   snes->forceiteration = force;
36283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3629be5caee7SBarry Smith }
3630be5caee7SBarry Smith 
363185216dc7SFande Kong /*@
3632f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
363385216dc7SFande Kong 
3634c3339decSBarry Smith   Logically Collective
363585216dc7SFande Kong 
36362fe279fdSBarry Smith   Input Parameter:
3637f6dfbefdSBarry Smith . snes - the `SNES` context
363885216dc7SFande Kong 
363985216dc7SFande Kong   Output Parameter:
3640dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
364185216dc7SFande Kong 
364206dd6b0eSSatish Balay   Level: intermediate
364306dd6b0eSSatish Balay 
36441cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
364585216dc7SFande Kong @*/
3646d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3647d71ae5a4SJacob Faibussowitsch {
364885216dc7SFande Kong   PetscFunctionBegin;
364985216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
365085216dc7SFande Kong   *force = snes->forceiteration;
36513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
365285216dc7SFande Kong }
3653be5caee7SBarry Smith 
3654be5caee7SBarry Smith /*@
3655f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
36569b94acceSBarry Smith 
3657c3339decSBarry Smith   Logically Collective
3658c7afd0dbSLois Curfman McInnes 
36599b94acceSBarry Smith   Input Parameters:
3660f6dfbefdSBarry Smith + snes   - the `SNES` context
366170441072SBarry Smith . abstol - absolute convergence tolerance
366233174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
36635358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3664f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
3665f6dfbefdSBarry Smith - maxf   - maximum number of function evaluations (-1 indicates no limit), default 1000
3666fee21e36SBarry Smith 
366733174efeSLois Curfman McInnes   Options Database Keys:
366870441072SBarry Smith + -snes_atol <abstol>    - Sets abstol
3669c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol>      - Sets rtol
3670c7afd0dbSLois Curfman McInnes . -snes_stol <stol>      - Sets stol
3671c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit>   - Sets maxit
3672c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf
36739b94acceSBarry Smith 
367436851e7fSLois Curfman McInnes   Level: intermediate
367536851e7fSLois Curfman McInnes 
36761cc06b55SBarry Smith .seealso: [](ch_snes), `SNESolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
36779b94acceSBarry Smith @*/
3678d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3679d71ae5a4SJacob Faibussowitsch {
36803a40ed3dSBarry Smith   PetscFunctionBegin;
36810700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3682c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3683c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3684c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3685c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3686c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3687c5eb9154SBarry Smith 
368813bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
36895f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3690ab54825eSJed Brown     snes->abstol = abstol;
3691ab54825eSJed Brown   }
369213bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
36935f80ce2aSJacob 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);
3694ab54825eSJed Brown     snes->rtol = rtol;
3695ab54825eSJed Brown   }
369613bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
36975f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3698c60f73f4SPeter Brune     snes->stol = stol;
3699ab54825eSJed Brown   }
3700ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
370163a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3702ab54825eSJed Brown     snes->max_its = maxit;
3703ab54825eSJed Brown   }
3704ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
370563a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3706ab54825eSJed Brown     snes->max_funcs = maxf;
3707ab54825eSJed Brown   }
370888976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
37093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37109b94acceSBarry Smith }
37119b94acceSBarry Smith 
3712e4d06f11SPatrick Farrell /*@
3713f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3714e4d06f11SPatrick Farrell 
3715c3339decSBarry Smith   Logically Collective
3716e4d06f11SPatrick Farrell 
3717e4d06f11SPatrick Farrell   Input Parameters:
3718f6dfbefdSBarry Smith + snes   - the `SNES` context
3719f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3720e4d06f11SPatrick Farrell 
3721f6dfbefdSBarry Smith   Options Database Key:
3722dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3723e4d06f11SPatrick Farrell 
3724e4d06f11SPatrick Farrell   Level: intermediate
3725e4d06f11SPatrick Farrell 
37261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3727e4d06f11SPatrick Farrell @*/
3728d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3729d71ae5a4SJacob Faibussowitsch {
3730e4d06f11SPatrick Farrell   PetscFunctionBegin;
3731e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3732e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3733e4d06f11SPatrick Farrell 
373413bcc0bdSJacob Faibussowitsch   if (divtol != (PetscReal)PETSC_DEFAULT) {
3735e4d06f11SPatrick Farrell     snes->divtol = divtol;
37369371c9d4SSatish Balay   } else {
3737e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3738e4d06f11SPatrick Farrell   }
37393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3740e4d06f11SPatrick Farrell }
3741e4d06f11SPatrick Farrell 
37429b94acceSBarry Smith /*@
374333174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
374433174efeSLois Curfman McInnes 
3745c7afd0dbSLois Curfman McInnes   Not Collective
3746c7afd0dbSLois Curfman McInnes 
374733174efeSLois Curfman McInnes   Input Parameters:
3748f6dfbefdSBarry Smith + snes  - the `SNES` context
374985385478SLisandro Dalcin . atol  - absolute convergence tolerance
375033174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
375133174efeSLois Curfman McInnes . stol  - convergence tolerance in terms of the norm
375233174efeSLois Curfman McInnes            of the change in the solution between steps
375333174efeSLois Curfman McInnes . maxit - maximum number of iterations
3754c7afd0dbSLois Curfman McInnes - maxf  - maximum number of function evaluations
3755fee21e36SBarry Smith 
375636851e7fSLois Curfman McInnes   Level: intermediate
375736851e7fSLois Curfman McInnes 
3758dc4c0fb0SBarry Smith   Note:
3759dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3760dc4c0fb0SBarry Smith 
37611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
376233174efeSLois Curfman McInnes @*/
3763d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3764d71ae5a4SJacob Faibussowitsch {
37653a40ed3dSBarry Smith   PetscFunctionBegin;
37660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
376785385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
376833174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3769c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
377033174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
377133174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
37723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377333174efeSLois Curfman McInnes }
377433174efeSLois Curfman McInnes 
3775e4d06f11SPatrick Farrell /*@
3776e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3777e4d06f11SPatrick Farrell 
3778e4d06f11SPatrick Farrell   Not Collective
3779e4d06f11SPatrick Farrell 
3780e4d06f11SPatrick Farrell   Input Parameters:
3781f6dfbefdSBarry Smith + snes   - the `SNES` context
3782e4d06f11SPatrick Farrell - divtol - divergence tolerance
3783e4d06f11SPatrick Farrell 
3784e4d06f11SPatrick Farrell   Level: intermediate
3785e4d06f11SPatrick Farrell 
37861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3787e4d06f11SPatrick Farrell @*/
3788d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3789d71ae5a4SJacob Faibussowitsch {
3790e4d06f11SPatrick Farrell   PetscFunctionBegin;
3791e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3792e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
37933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3794e4d06f11SPatrick Farrell }
3795e4d06f11SPatrick Farrell 
379633174efeSLois Curfman McInnes /*@
37979b94acceSBarry Smith   SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
37989b94acceSBarry Smith 
3799c3339decSBarry Smith   Logically Collective
3800fee21e36SBarry Smith 
3801c7afd0dbSLois Curfman McInnes   Input Parameters:
3802f6dfbefdSBarry Smith + snes - the `SNES` context
3803c7afd0dbSLois Curfman McInnes - tol  - tolerance
3804c7afd0dbSLois Curfman McInnes 
38059b94acceSBarry Smith   Options Database Key:
38064a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol
38079b94acceSBarry Smith 
380836851e7fSLois Curfman McInnes   Level: intermediate
380936851e7fSLois Curfman McInnes 
38101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
38119b94acceSBarry Smith @*/
3812d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3813d71ae5a4SJacob Faibussowitsch {
38143a40ed3dSBarry Smith   PetscFunctionBegin;
38150700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3816c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
38179b94acceSBarry Smith   snes->deltatol = tol;
38183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38199b94acceSBarry Smith }
38209b94acceSBarry Smith 
38216ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
38226ba87a44SLisandro Dalcin 
3823d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3824d71ae5a4SJacob Faibussowitsch {
3825b271bb04SBarry Smith   PetscDrawLG      lg;
3826b271bb04SBarry Smith   PetscReal        x, y, per;
3827b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3828b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3829b271bb04SBarry Smith   PetscDraw        draw;
3830b271bb04SBarry Smith 
3831459f5d12SBarry Smith   PetscFunctionBegin;
38324d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
38339566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
38349566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38359566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38369566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3837b271bb04SBarry Smith   x = (PetscReal)n;
383877b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
383994c9c6d3SKarl Rupp   else y = -15.0;
38409566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38416934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38429566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38439566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3844b271bb04SBarry Smith   }
3845b271bb04SBarry Smith 
38469566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
38479566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38489566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
3849aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
38509566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3851b271bb04SBarry Smith   x = (PetscReal)n;
3852b271bb04SBarry Smith   y = 100.0 * per;
38539566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38546934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38559566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38569566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3857b271bb04SBarry Smith   }
3858b271bb04SBarry Smith 
38599566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
38609371c9d4SSatish Balay   if (!n) {
38619371c9d4SSatish Balay     prev = rnorm;
38629371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
38639371c9d4SSatish Balay   }
38649566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38659566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3866b271bb04SBarry Smith   x = (PetscReal)n;
3867b271bb04SBarry Smith   y = (prev - rnorm) / prev;
38689566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38696934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38709566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38719566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3872b271bb04SBarry Smith   }
3873b271bb04SBarry Smith 
38749566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
38759566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38769566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38779566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3878b271bb04SBarry Smith   x = (PetscReal)n;
3879b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3880b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
38819566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3882b271bb04SBarry Smith   }
38836934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38849566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38859566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3886b271bb04SBarry Smith   }
3887b271bb04SBarry Smith   prev = rnorm;
38883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3889b271bb04SBarry Smith }
3890b271bb04SBarry Smith 
3891228d79bcSJed Brown /*@
38922d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
38932d157150SStefano Zampini 
38942d157150SStefano Zampini   Collective
38952d157150SStefano Zampini 
38962d157150SStefano Zampini   Input Parameters:
38972d157150SStefano Zampini + snes  - the `SNES` context
38982d157150SStefano Zampini . it    - current iteration
38992d157150SStefano Zampini . xnorm - 2-norm of current iterate
39002d157150SStefano Zampini . snorm - 2-norm of current step
39012d157150SStefano Zampini - fnorm - 2-norm of function
39022d157150SStefano Zampini 
39032d157150SStefano Zampini   Level: developer
39042d157150SStefano Zampini 
39052d157150SStefano Zampini   Note:
39062d157150SStefano Zampini   This routine is called by the `SNES` implementations.
39072d157150SStefano Zampini   It does not typically need to be called by the user.
39082d157150SStefano Zampini 
3909be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
39102d157150SStefano Zampini @*/
39112d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
39122d157150SStefano Zampini {
39132d157150SStefano Zampini   PetscFunctionBegin;
39142d157150SStefano Zampini   if (!snes->reason) {
39152d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
39162d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
39172d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
39182d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
39192d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
39202d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
39212d157150SStefano Zampini     }
39222d157150SStefano Zampini   }
39232d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
39242d157150SStefano Zampini }
39252d157150SStefano Zampini 
39262d157150SStefano Zampini /*@
3927228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
3928228d79bcSJed Brown 
3929c3339decSBarry Smith   Collective
3930228d79bcSJed Brown 
3931228d79bcSJed Brown   Input Parameters:
3932f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
3933228d79bcSJed Brown . iter  - iteration number
3934228d79bcSJed Brown - rnorm - relative norm of the residual
3935228d79bcSJed Brown 
3936dc4c0fb0SBarry Smith   Level: developer
3937dc4c0fb0SBarry Smith 
3938f6dfbefdSBarry Smith   Note:
3939f6dfbefdSBarry Smith   This routine is called by the `SNES` implementations.
3940228d79bcSJed Brown   It does not typically need to be called by the user.
3941228d79bcSJed Brown 
39421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
3943228d79bcSJed Brown @*/
3944d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
3945d71ae5a4SJacob Faibussowitsch {
39467a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
39477a03ce2fSLisandro Dalcin 
39487a03ce2fSLisandro Dalcin   PetscFunctionBegin;
3949*5f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
39509566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
395148a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
39529566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
39533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39547a03ce2fSLisandro Dalcin }
39557a03ce2fSLisandro Dalcin 
39569b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
39579b94acceSBarry Smith 
3958bf388a1fSBarry Smith /*MC
3959f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
3960bf388a1fSBarry Smith 
3961bf388a1fSBarry Smith      Synopsis:
3962aaa7dc30SBarry Smith      #include <petscsnes.h>
396337fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
3964bf388a1fSBarry Smith 
3965c3339decSBarry Smith      Collective
39661843f636SBarry Smith 
39671843f636SBarry Smith     Input Parameters:
3968f6dfbefdSBarry Smith +    snes - the `SNES` context
3969bf388a1fSBarry Smith .    its - iteration number
3970bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
3971bf388a1fSBarry Smith -    mctx - [optional] monitoring context
3972bf388a1fSBarry Smith 
3973878cb397SSatish Balay    Level: advanced
3974878cb397SSatish Balay 
39751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
3976bf388a1fSBarry Smith M*/
3977bf388a1fSBarry Smith 
39789b94acceSBarry Smith /*@C
3979a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
39809b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
39819b94acceSBarry Smith   progress.
39829b94acceSBarry Smith 
3983c3339decSBarry Smith   Logically Collective
3984fee21e36SBarry Smith 
3985c7afd0dbSLois Curfman McInnes   Input Parameters:
3986f6dfbefdSBarry Smith + snes           - the `SNES` context
398720f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
3988b8a78c4aSBarry Smith . mctx           - [optional] user-defined context for private data for the
3989dc4c0fb0SBarry Smith           monitor routine (use `NULL` if no context is desired)
3990dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
39919b94acceSBarry Smith 
39929665c990SLois Curfman McInnes   Options Database Keys:
3993f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
3994798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
3995dc4c0fb0SBarry 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
3996c7afd0dbSLois Curfman McInnes                             the options database.
39979665c990SLois Curfman McInnes 
3998dc4c0fb0SBarry Smith   Level: intermediate
3999dc4c0fb0SBarry Smith 
4000f6dfbefdSBarry Smith   Note:
40016bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4002f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
40036bc08f3fSLois Curfman McInnes   order in which they were set.
4004639f9d9dSBarry Smith 
4005e4094ef1SJacob Faibussowitsch   Fortran Notes:
4006f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4007025f1a04SBarry Smith 
40081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
40099b94acceSBarry Smith @*/
4010d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4011d71ae5a4SJacob Faibussowitsch {
4012b90d0a6eSBarry Smith   PetscInt  i;
401378064530SBarry Smith   PetscBool identical;
4014b90d0a6eSBarry Smith 
40153a40ed3dSBarry Smith   PetscFunctionBegin;
40160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4017b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
40189566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
40193ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4020649052a6SBarry Smith   }
40215f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
40226e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4023b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4024639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
40253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40269b94acceSBarry Smith }
40279b94acceSBarry Smith 
4028a278d85bSSatish Balay /*@
4029f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
40305cd90555SBarry Smith 
4031c3339decSBarry Smith   Logically Collective
4032c7afd0dbSLois Curfman McInnes 
40332fe279fdSBarry Smith   Input Parameter:
4034f6dfbefdSBarry Smith . snes - the `SNES` context
40355cd90555SBarry Smith 
40361a480d89SAdministrator   Options Database Key:
4037a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4038dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4039c7afd0dbSLois Curfman McInnes     set via the options database
40405cd90555SBarry Smith 
4041dc4c0fb0SBarry Smith   Level: intermediate
4042dc4c0fb0SBarry Smith 
4043f6dfbefdSBarry Smith   Note:
4044f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
40455cd90555SBarry Smith 
40461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
40475cd90555SBarry Smith @*/
4048d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4049d71ae5a4SJacob Faibussowitsch {
4050d952e501SBarry Smith   PetscInt i;
4051d952e501SBarry Smith 
40525cd90555SBarry Smith   PetscFunctionBegin;
40530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4054d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
405548a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4056d952e501SBarry Smith   }
40575cd90555SBarry Smith   snes->numbermonitors = 0;
40583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40595cd90555SBarry Smith }
40605cd90555SBarry Smith 
4061bf388a1fSBarry Smith /*MC
4062bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4063bf388a1fSBarry Smith 
4064bf388a1fSBarry Smith      Synopsis:
4065aaa7dc30SBarry Smith      #include <petscsnes.h>
406637fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4067bf388a1fSBarry Smith 
4068c3339decSBarry Smith      Collective
40691843f636SBarry Smith 
40701843f636SBarry Smith     Input Parameters:
4071f6dfbefdSBarry Smith +    snes - the `SNES` context
4072bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4073bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4074bf388a1fSBarry Smith .    gnorm - 2-norm of current step
40751843f636SBarry Smith .    f - 2-norm of function
40761843f636SBarry Smith -    cctx - [optional] convergence context
40771843f636SBarry Smith 
40781843f636SBarry Smith     Output Parameter:
40791843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4080bf388a1fSBarry Smith 
4081878cb397SSatish Balay    Level: intermediate
4082bf388a1fSBarry Smith 
40831cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4084bf388a1fSBarry Smith M*/
4085bf388a1fSBarry Smith 
40869b94acceSBarry Smith /*@C
40879b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
40889b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
40899b94acceSBarry Smith 
4090c3339decSBarry Smith   Logically Collective
4091fee21e36SBarry Smith 
4092c7afd0dbSLois Curfman McInnes   Input Parameters:
4093f6dfbefdSBarry Smith + snes                        - the `SNES` context
4094e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4095dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4096dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
40979b94acceSBarry Smith 
409836851e7fSLois Curfman McInnes   Level: advanced
409936851e7fSLois Curfman McInnes 
41001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
41019b94acceSBarry Smith @*/
4102d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4103d71ae5a4SJacob Faibussowitsch {
41043a40ed3dSBarry Smith   PetscFunctionBegin;
41050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4106e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
41071baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4108bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
41097f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
411085385478SLisandro Dalcin   snes->cnvP                  = cctx;
41113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41129b94acceSBarry Smith }
41139b94acceSBarry Smith 
411452baeb72SSatish Balay /*@
4115f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4116184914b5SBarry Smith 
4117184914b5SBarry Smith   Not Collective
4118184914b5SBarry Smith 
4119184914b5SBarry Smith   Input Parameter:
4120f6dfbefdSBarry Smith . snes - the `SNES` context
4121184914b5SBarry Smith 
4122184914b5SBarry Smith   Output Parameter:
4123f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4124184914b5SBarry Smith 
4125f6dfbefdSBarry Smith   Options Database Key:
41266a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
41276a4d7782SBarry Smith 
4128184914b5SBarry Smith   Level: intermediate
4129184914b5SBarry Smith 
4130f6dfbefdSBarry Smith   Note:
4131f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4132184914b5SBarry Smith 
41331cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4134184914b5SBarry Smith @*/
4135d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4136d71ae5a4SJacob Faibussowitsch {
4137184914b5SBarry Smith   PetscFunctionBegin;
41380700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41394482741eSBarry Smith   PetscValidPointer(reason, 2);
4140184914b5SBarry Smith   *reason = snes->reason;
41413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4142184914b5SBarry Smith }
4143184914b5SBarry Smith 
4144c4421ceaSFande Kong /*@C
4145f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4146c4421ceaSFande Kong 
4147c4421ceaSFande Kong   Not Collective
4148c4421ceaSFande Kong 
4149c4421ceaSFande Kong   Input Parameter:
4150f6dfbefdSBarry Smith . snes - the `SNES` context
4151c4421ceaSFande Kong 
4152c4421ceaSFande Kong   Output Parameter:
4153dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4154c4421ceaSFande Kong 
415599c90e12SSatish Balay   Level: beginner
4156c4421ceaSFande Kong 
41571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4158c4421ceaSFande Kong @*/
4159d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4160d71ae5a4SJacob Faibussowitsch {
4161c4421ceaSFande Kong   PetscFunctionBegin;
4162c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4163dadcf809SJacob Faibussowitsch   PetscValidPointer(strreason, 2);
4164c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
41653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4166c4421ceaSFande Kong }
4167c4421ceaSFande Kong 
416833866048SMatthew G. Knepley /*@
4169f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
417033866048SMatthew G. Knepley 
417133866048SMatthew G. Knepley   Not Collective
417233866048SMatthew G. Knepley 
417333866048SMatthew G. Knepley   Input Parameters:
4174f6dfbefdSBarry Smith + snes   - the `SNES` context
4175f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
417633866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
417733866048SMatthew G. Knepley 
4178f6dfbefdSBarry Smith   Level: developer
4179f6dfbefdSBarry Smith 
4180e4094ef1SJacob Faibussowitsch   Developer Notes:
4181f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
418233866048SMatthew G. Knepley 
41831cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
418433866048SMatthew G. Knepley @*/
4185d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4186d71ae5a4SJacob Faibussowitsch {
418733866048SMatthew G. Knepley   PetscFunctionBegin;
418833866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4189*5f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
419033866048SMatthew G. Knepley   snes->reason = reason;
41913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
419233866048SMatthew G. Knepley }
419333866048SMatthew G. Knepley 
4194c9005455SLois Curfman McInnes /*@
4195c9005455SLois Curfman McInnes   SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
4196c9005455SLois Curfman McInnes 
4197c3339decSBarry Smith   Logically Collective
4198fee21e36SBarry Smith 
4199c7afd0dbSLois Curfman McInnes   Input Parameters:
4200f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
42018c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4202cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4203758f92a0SBarry Smith . na    - size of a and its
4204f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4205758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4206c7afd0dbSLois Curfman McInnes 
4207dc4c0fb0SBarry Smith   Level: intermediate
4208dc4c0fb0SBarry Smith 
4209308dcc3eSBarry Smith   Notes:
4210dc4c0fb0SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4211308dcc3eSBarry Smith   default array of length 10000 is allocated.
4212308dcc3eSBarry Smith 
4213c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4214c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4215c9005455SLois Curfman McInnes   during the section of code that is being timed.
4216c9005455SLois Curfman McInnes 
42171cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4218c9005455SLois Curfman McInnes @*/
4219d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4220d71ae5a4SJacob Faibussowitsch {
42213a40ed3dSBarry Smith   PetscFunctionBegin;
42220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4223064a246eSJacob Faibussowitsch   if (a) PetscValidRealPointer(a, 2);
4224a562a398SLisandro Dalcin   if (its) PetscValidIntPointer(its, 3);
42257a1ec6d4SBarry Smith   if (!a) {
4226308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
42279566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4228071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4229308dcc3eSBarry Smith   }
4230c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4231758f92a0SBarry Smith   snes->conv_hist_its   = its;
4232115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4233a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4234758f92a0SBarry Smith   snes->conv_hist_reset = reset;
42353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4236758f92a0SBarry Smith }
4237758f92a0SBarry Smith 
4238d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4239c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4240c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
424199e0435eSBarry Smith 
4242d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4243d71ae5a4SJacob Faibussowitsch {
4244308dcc3eSBarry Smith   mxArray   *mat;
4245308dcc3eSBarry Smith   PetscInt   i;
4246308dcc3eSBarry Smith   PetscReal *ar;
4247308dcc3eSBarry Smith 
4248308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4249308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4250f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
425111cc89d2SBarry Smith   return mat;
4252308dcc3eSBarry Smith }
4253308dcc3eSBarry Smith #endif
4254308dcc3eSBarry Smith 
42550c4c9dddSBarry Smith /*@C
4256758f92a0SBarry Smith   SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
4257758f92a0SBarry Smith 
42583f9fe445SBarry Smith   Not Collective
4259758f92a0SBarry Smith 
4260758f92a0SBarry Smith   Input Parameter:
4261f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4262758f92a0SBarry Smith 
4263758f92a0SBarry Smith   Output Parameters:
4264f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4265758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4266758f92a0SBarry Smith          negative if not converged) for each solve.
426720f4b53cSBarry Smith - na  - size of `a` and `its`
4268758f92a0SBarry Smith 
4269dc4c0fb0SBarry Smith   Level: intermediate
4270dc4c0fb0SBarry Smith 
427120f4b53cSBarry Smith   Note:
427220f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
427320f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
427420f4b53cSBarry Smith   during the section of code that is being timed.
427520f4b53cSBarry Smith 
4276e4094ef1SJacob Faibussowitsch   Fortran Notes:
4277758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4278dc4c0fb0SBarry Smith .vb
4279dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4280dc4c0fb0SBarry Smith .ve
4281758f92a0SBarry Smith 
42821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4283758f92a0SBarry Smith @*/
4284d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4285d71ae5a4SJacob Faibussowitsch {
4286758f92a0SBarry Smith   PetscFunctionBegin;
42870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4288758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4289758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4290115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
42913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4292c9005455SLois Curfman McInnes }
4293c9005455SLois Curfman McInnes 
4294ac226902SBarry Smith /*@C
429576b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4296eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
42977e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
429876b2cf59SMatthew Knepley 
4299c3339decSBarry Smith   Logically Collective
430076b2cf59SMatthew Knepley 
430176b2cf59SMatthew Knepley   Input Parameters:
4302a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4303a2b725a8SWilliam Gropp - func - The function
430476b2cf59SMatthew Knepley 
430520f4b53cSBarry Smith   Calling sequence of `func`:
430620f4b53cSBarry Smith $ PetscErrorCode func(SNES snes, PetscInt step);
430720f4b53cSBarry Smith + snes - the nonlinear solver context
430820f4b53cSBarry Smith - step - The current step of the iteration
430976b2cf59SMatthew Knepley 
4310fe97e370SBarry Smith   Level: advanced
4311fe97e370SBarry Smith 
43126b7fb656SBarry Smith   Note:
4313f6dfbefdSBarry 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
4314f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
4315fe97e370SBarry Smith   This is not used by most users.
431676b2cf59SMatthew Knepley 
4317aaa8cc7dSPierre 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.
43186b7fb656SBarry Smith 
4319e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4320db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
432176b2cf59SMatthew Knepley @*/
43220b4db180SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES snes, PetscInt step))
4323d71ae5a4SJacob Faibussowitsch {
432476b2cf59SMatthew Knepley   PetscFunctionBegin;
43250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4326e7788613SBarry Smith   snes->ops->update = func;
43273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
432876b2cf59SMatthew Knepley }
432976b2cf59SMatthew Knepley 
433091f3e32bSBarry Smith /*@C
4331f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
43322a359c20SBarry Smith 
4333c3339decSBarry Smith   Collective
43342a359c20SBarry Smith 
4335e4094ef1SJacob Faibussowitsch   Input Parameters:
4336f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
43372a359c20SBarry Smith - viewer - the viewer to display the reason
43382a359c20SBarry Smith 
43392a359c20SBarry Smith   Options Database Keys:
4340ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4341ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4342eafd5ff0SAlex Lindsay 
4343f6dfbefdSBarry Smith   Note:
4344f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4345f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
43462a359c20SBarry Smith 
43472a359c20SBarry Smith   Level: beginner
43482a359c20SBarry Smith 
43491cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4350f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4351f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4352db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
43532a359c20SBarry Smith @*/
4354d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4355d71ae5a4SJacob Faibussowitsch {
435675cca76cSMatthew G. Knepley   PetscViewerFormat format;
43572a359c20SBarry Smith   PetscBool         isAscii;
43582a359c20SBarry Smith 
43592a359c20SBarry Smith   PetscFunctionBegin;
436019a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
43619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
43622a359c20SBarry Smith   if (isAscii) {
43639566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
43649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
436575cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
436675cca76cSMatthew G. Knepley       DM       dm;
436775cca76cSMatthew G. Knepley       Vec      u;
436875cca76cSMatthew G. Knepley       PetscDS  prob;
436975cca76cSMatthew G. Knepley       PetscInt Nf, f;
437095cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
437195cbbfd3SMatthew G. Knepley       void    **exactCtx;
437275cca76cSMatthew G. Knepley       PetscReal error;
437375cca76cSMatthew G. Knepley 
43749566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
43759566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
43769566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
43779566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
43789566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
43799566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
43809566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
43819566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
43829566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
438363a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
438475cca76cSMatthew G. Knepley     }
4385eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
43862a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
438763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
43882a359c20SBarry Smith       } else {
438963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
43902a359c20SBarry Smith       }
4391eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
43922a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
439363a3b9bcSJacob 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));
43942a359c20SBarry Smith       } else {
439563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
43962a359c20SBarry Smith       }
43972a359c20SBarry Smith     }
43989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
43992a359c20SBarry Smith   }
44003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44012a359c20SBarry Smith }
44022a359c20SBarry Smith 
4403c4421ceaSFande Kong /*@C
4404c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4405aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4406c4421ceaSFande Kong 
4407c3339decSBarry Smith   Logically Collective
4408c4421ceaSFande Kong 
4409c4421ceaSFande Kong   Input Parameters:
4410f6dfbefdSBarry Smith + snes              - the `SNES` context
4411c4421ceaSFande Kong . f                 - the snes converged reason view function
4412c4421ceaSFande Kong . vctx              - [optional] user-defined context for private data for the
4413dc4c0fb0SBarry Smith           snes converged reason view routine (use `NULL` if no context is desired)
4414dc4c0fb0SBarry Smith - reasonviewdestroy - [optional] routine that frees reasonview context (may be `NULL`)
4415c4421ceaSFande Kong 
4416c4421ceaSFande Kong   Options Database Keys:
4417f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4418c4421ceaSFande Kong - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have
4419c4421ceaSFande Kong                             been hardwired into a code by
4420f6dfbefdSBarry Smith                             calls to `SNESConvergedReasonViewSet()`, but
4421c4421ceaSFande Kong                             does not cancel those set via
4422c4421ceaSFande Kong                             the options database.
4423c4421ceaSFande Kong 
4424dc4c0fb0SBarry Smith   Level: intermediate
4425dc4c0fb0SBarry Smith 
4426f6dfbefdSBarry Smith   Note:
4427c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4428f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4429c4421ceaSFande Kong   order in which they were set.
4430c4421ceaSFande Kong 
44311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4432c4421ceaSFande Kong @*/
4433d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES, void *), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **))
4434d71ae5a4SJacob Faibussowitsch {
4435c4421ceaSFande Kong   PetscInt  i;
4436c4421ceaSFande Kong   PetscBool identical;
4437c4421ceaSFande Kong 
4438c4421ceaSFande Kong   PetscFunctionBegin;
4439c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4440c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
44419566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
44423ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4443c4421ceaSFande Kong   }
44445f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4445c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4446c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4447c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
44483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4449c4421ceaSFande Kong }
4450c4421ceaSFande Kong 
445191f3e32bSBarry Smith /*@
4452f6dfbefdSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed.
4453c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
44542a359c20SBarry Smith 
4455c3339decSBarry Smith   Collective
44562a359c20SBarry Smith 
44572fe279fdSBarry Smith   Input Parameter:
4458f6dfbefdSBarry Smith . snes - the `SNES` object
44592a359c20SBarry Smith 
4460f6dfbefdSBarry Smith   Level: advanced
44612a359c20SBarry Smith 
44621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4463f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
44642a359c20SBarry Smith @*/
4465d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4466d71ae5a4SJacob Faibussowitsch {
44672a359c20SBarry Smith   PetscViewer       viewer;
44682a359c20SBarry Smith   PetscBool         flg;
44692a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
44702a359c20SBarry Smith   PetscViewerFormat format;
4471c4421ceaSFande Kong   PetscInt          i;
44722a359c20SBarry Smith 
44732a359c20SBarry Smith   PetscFunctionBegin;
44743ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
44752a359c20SBarry Smith   incall = PETSC_TRUE;
4476c4421ceaSFande Kong 
4477c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
447848a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4479c4421ceaSFande Kong 
4480c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
44819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
44822a359c20SBarry Smith   if (flg) {
44839566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
44849566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
44859566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
44869566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
44872a359c20SBarry Smith   }
44882a359c20SBarry Smith   incall = PETSC_FALSE;
44893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44902a359c20SBarry Smith }
44912a359c20SBarry Smith 
4492487a658cSBarry Smith /*@
4493f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
4494f6dfbefdSBarry Smith   Call `SNESSolve()` after calling `SNESCreate()` and optional routines of the form `SNESSetXXX()`.
44959b94acceSBarry Smith 
4496c3339decSBarry Smith   Collective
4497c7afd0dbSLois Curfman McInnes 
4498b2002411SLois Curfman McInnes   Input Parameters:
4499f6dfbefdSBarry Smith + snes - the `SNES` context
4500dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
450185385478SLisandro Dalcin - x    - the solution vector.
45029b94acceSBarry Smith 
4503dc4c0fb0SBarry Smith   Level: beginner
4504dc4c0fb0SBarry Smith 
4505f6dfbefdSBarry Smith   Note:
45068ddd3da0SLois Curfman McInnes   The user should initialize the vector,x, with the initial guess
4507f6dfbefdSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()`.  In particular,
45088ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4509f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
45108ddd3da0SLois Curfman McInnes 
45111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4512db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4513db781477SPatrick Sanan           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
45149b94acceSBarry Smith @*/
4515d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4516d71ae5a4SJacob Faibussowitsch {
4517ace3abfcSBarry Smith   PetscBool flg;
4518efd51863SBarry Smith   PetscInt  grid;
45190298fd71SBarry Smith   Vec       xcreated = NULL;
4520caa4e7f2SJed Brown   DM        dm;
4521052efed2SBarry Smith 
45223a40ed3dSBarry Smith   PetscFunctionBegin;
45230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4524a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4525a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
45260700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
452785385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
452885385478SLisandro Dalcin 
452934b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
453006fc46c8SMatthew G. Knepley   {
453106fc46c8SMatthew G. Knepley     PetscViewer       viewer;
453206fc46c8SMatthew G. Knepley     PetscViewerFormat format;
45337c88af5aSMatthew G. Knepley     PetscInt          num;
453406fc46c8SMatthew G. Knepley     PetscBool         flg;
453506fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
453606fc46c8SMatthew G. Knepley 
453706fc46c8SMatthew G. Knepley     if (!incall) {
453834b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
45399566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
454006fc46c8SMatthew G. Knepley       if (flg) {
454106fc46c8SMatthew G. Knepley         PetscConvEst conv;
454246079b62SMatthew G. Knepley         DM           dm;
454346079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
454446079b62SMatthew G. Knepley         PetscInt     Nf;
454506fc46c8SMatthew G. Knepley 
454606fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
45479566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
45489566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
45499566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
45509566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
45519566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
45529566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
45539566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
45549566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
45559566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
45569566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
45579566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
45589566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
45599566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
45609566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
456106fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
456206fc46c8SMatthew G. Knepley       }
456334b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4564b2588ea6SMatthew G. Knepley       num = 1;
45659566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
456634b4d3a8SMatthew G. Knepley       if (flg) {
456734b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
456834b4d3a8SMatthew G. Knepley 
456934b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
45709566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
45719566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
45729566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
45739566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
45749566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
45759566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
45769566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
457734b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
457834b4d3a8SMatthew G. Knepley       }
45797c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
45807c88af5aSMatthew G. Knepley       num = 0;
45819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
45827c88af5aSMatthew G. Knepley       if (num) {
45837c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
45847c88af5aSMatthew G. Knepley 
45857c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
45869566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
45879566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
45889566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
45899566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
45909566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
45919566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
45929566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
45937c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
45947c88af5aSMatthew G. Knepley       }
459506fc46c8SMatthew G. Knepley     }
459606fc46c8SMatthew G. Knepley   }
4597ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4598caa4e7f2SJed Brown   if (!x) {
45999566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
46009566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4601a69afd8bSBarry Smith     x = xcreated;
4602a69afd8bSBarry Smith   }
46039566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4604f05ece33SBarry Smith 
46059566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4606efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
460785385478SLisandro Dalcin     /* set solution vector */
46089566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
46099566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
461085385478SLisandro Dalcin     snes->vec_sol = x;
46119566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4612caa4e7f2SJed Brown 
4613caa4e7f2SJed Brown     /* set affine vector if provided */
46149566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
46159566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
461685385478SLisandro Dalcin     snes->vec_rhs = b;
461785385478SLisandro Dalcin 
46185f80ce2aSJacob 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");
46195f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
46205f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector");
4621aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
46229566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
46239566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
46243f149594SLisandro Dalcin 
46257eee914bSBarry Smith     if (!grid) {
462625e27a38SBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4627dd568438SSatish Balay     }
4628d25893d9SBarry Smith 
4629abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
46309371c9d4SSatish Balay     if (snes->counters_reset) {
46319371c9d4SSatish Balay       snes->nfuncs      = 0;
46329371c9d4SSatish Balay       snes->linear_its  = 0;
46339371c9d4SSatish Balay       snes->numFailures = 0;
46349371c9d4SSatish Balay     }
4635d5e45103SBarry Smith 
46362d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
46379566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4638dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
46399566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
46402d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4641422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
46423f149594SLisandro Dalcin 
464337ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
464437ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
464537ec4e1aSPeter Brune 
46469566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
46479566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4648c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
46499566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
46505968eb51SBarry Smith 
46515f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
46529c8e83a9SBarry Smith     if (snes->reason < 0) break;
4653efd51863SBarry Smith     if (grid < snes->gridsequence) {
4654efd51863SBarry Smith       DM  fine;
4655efd51863SBarry Smith       Vec xnew;
4656efd51863SBarry Smith       Mat interp;
4657efd51863SBarry Smith 
46589566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
46595f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
46609566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
46619566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
46629566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
46639566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
46649566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4665efd51863SBarry Smith       x = xnew;
4666efd51863SBarry Smith 
46679566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
46689566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
46699566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
46709566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
46719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4672efd51863SBarry Smith     }
4673efd51863SBarry Smith   }
46749566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
46759566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
46769566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
46779566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
46783f7e2da0SPeter Brune 
46799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
46809566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
46813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46829b94acceSBarry Smith }
46839b94acceSBarry Smith 
46849b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
46859b94acceSBarry Smith 
468682bf6240SBarry Smith /*@C
46874b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
46889b94acceSBarry Smith 
4689c3339decSBarry Smith   Collective
4690fee21e36SBarry Smith 
4691c7afd0dbSLois Curfman McInnes   Input Parameters:
4692f6dfbefdSBarry Smith + snes - the `SNES` context
4693454a90a3SBarry Smith - type - a known method
4694c7afd0dbSLois Curfman McInnes 
4695c7afd0dbSLois Curfman McInnes   Options Database Key:
4696454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
469704d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4698ae12b187SLois Curfman McInnes 
4699dc4c0fb0SBarry Smith   Level: intermediate
4700dc4c0fb0SBarry Smith 
47019b94acceSBarry Smith   Notes:
4702e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4703f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4704c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
47054a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4706c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
47079b94acceSBarry Smith 
4708f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4709f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4710ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4711ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4712f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4713ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4714ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4715ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4716ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4717b0a32e0cSBarry Smith   appropriate method.
471836851e7fSLois Curfman McInnes 
4719e4094ef1SJacob Faibussowitsch   Developer Notes:
4720f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4721f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
47228f6c3df8SBarry Smith 
47231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
47249b94acceSBarry Smith @*/
4725d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4726d71ae5a4SJacob Faibussowitsch {
4727ace3abfcSBarry Smith   PetscBool match;
47285f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
47293a40ed3dSBarry Smith 
47303a40ed3dSBarry Smith   PetscFunctionBegin;
47310700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47324482741eSBarry Smith   PetscValidCharPointer(type, 2);
473382bf6240SBarry Smith 
47349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
47353ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
473692ff6ae8SBarry Smith 
47379566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
47386adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
473975396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4740dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
474175396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
47429e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
47439e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
47449e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
47459e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
47469e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
47477fe760d5SStefano Zampini 
47487fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
47499566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
47507fe760d5SStefano Zampini 
475175396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
475275396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4753f5af7f23SKarl Rupp 
47549566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
47559566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
47563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47579b94acceSBarry Smith }
47589b94acceSBarry Smith 
47599b94acceSBarry Smith /*@C
4760f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
47619b94acceSBarry Smith 
4762c7afd0dbSLois Curfman McInnes   Not Collective
4763c7afd0dbSLois Curfman McInnes 
47649b94acceSBarry Smith   Input Parameter:
47654b0e389bSBarry Smith . snes - nonlinear solver context
47669b94acceSBarry Smith 
47679b94acceSBarry Smith   Output Parameter:
4768f6dfbefdSBarry Smith . type - `SNES` method (a character string)
47699b94acceSBarry Smith 
477036851e7fSLois Curfman McInnes   Level: intermediate
477136851e7fSLois Curfman McInnes 
47721cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
47739b94acceSBarry Smith @*/
4774d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4775d71ae5a4SJacob Faibussowitsch {
47763a40ed3dSBarry Smith   PetscFunctionBegin;
47770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47784482741eSBarry Smith   PetscValidPointer(type, 2);
47797adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
47803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47819b94acceSBarry Smith }
47829b94acceSBarry Smith 
47833cd8a7caSMatthew G. Knepley /*@
4784f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
47853cd8a7caSMatthew G. Knepley 
4786c3339decSBarry Smith   Logically Collective
47873cd8a7caSMatthew G. Knepley 
47883cd8a7caSMatthew G. Knepley   Input Parameters:
4789f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
47903cd8a7caSMatthew G. Knepley - u    - the solution vector
47913cd8a7caSMatthew G. Knepley 
47923cd8a7caSMatthew G. Knepley   Level: beginner
47933cd8a7caSMatthew G. Knepley 
47941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
47953cd8a7caSMatthew G. Knepley @*/
4796d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4797d71ae5a4SJacob Faibussowitsch {
47983cd8a7caSMatthew G. Knepley   DM dm;
47993cd8a7caSMatthew G. Knepley 
48003cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
48013cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48023cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
48039566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
48049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
48053cd8a7caSMatthew G. Knepley 
48063cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
48073cd8a7caSMatthew G. Knepley 
48089566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
48099566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
48103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48113cd8a7caSMatthew G. Knepley }
48123cd8a7caSMatthew G. Knepley 
481352baeb72SSatish Balay /*@
48149b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
4815f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
48169b94acceSBarry Smith 
4817f6dfbefdSBarry Smith   Not Collective, but x is parallel if snes is parallel
4818c7afd0dbSLois Curfman McInnes 
48199b94acceSBarry Smith   Input Parameter:
4820f6dfbefdSBarry Smith . snes - the `SNES` context
48219b94acceSBarry Smith 
48229b94acceSBarry Smith   Output Parameter:
48239b94acceSBarry Smith . x - the solution
48249b94acceSBarry Smith 
482570e92668SMatthew Knepley   Level: intermediate
482636851e7fSLois Curfman McInnes 
48271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
48289b94acceSBarry Smith @*/
4829d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4830d71ae5a4SJacob Faibussowitsch {
48313a40ed3dSBarry Smith   PetscFunctionBegin;
48320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48334482741eSBarry Smith   PetscValidPointer(x, 2);
483485385478SLisandro Dalcin   *x = snes->vec_sol;
48353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
483670e92668SMatthew Knepley }
483770e92668SMatthew Knepley 
483852baeb72SSatish Balay /*@
48399b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
48409b94acceSBarry Smith   stored.
48419b94acceSBarry Smith 
4842f6dfbefdSBarry Smith   Not Collective, but x is parallel if snes is parallel
4843c7afd0dbSLois Curfman McInnes 
48449b94acceSBarry Smith   Input Parameter:
4845f6dfbefdSBarry Smith . snes - the `SNES` context
48469b94acceSBarry Smith 
48479b94acceSBarry Smith   Output Parameter:
48489b94acceSBarry Smith . x - the solution update
48499b94acceSBarry Smith 
485036851e7fSLois Curfman McInnes   Level: advanced
485136851e7fSLois Curfman McInnes 
48521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
48539b94acceSBarry Smith @*/
4854d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4855d71ae5a4SJacob Faibussowitsch {
48563a40ed3dSBarry Smith   PetscFunctionBegin;
48570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48584482741eSBarry Smith   PetscValidPointer(x, 2);
485985385478SLisandro Dalcin   *x = snes->vec_sol_update;
48603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48619b94acceSBarry Smith }
48629b94acceSBarry Smith 
48639b94acceSBarry Smith /*@C
4864f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
48659b94acceSBarry Smith 
4866f6dfbefdSBarry Smith   Not Collective, but r is parallel if snes is parallel. Collective if r is requested, but has not been created yet.
4867c7afd0dbSLois Curfman McInnes 
48689b94acceSBarry Smith   Input Parameter:
4869f6dfbefdSBarry Smith . snes - the `SNES` context
48709b94acceSBarry Smith 
4871d8d19677SJose E. Roman   Output Parameters:
4872dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
487320f4b53cSBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunction`
4874dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
48759b94acceSBarry Smith 
487636851e7fSLois Curfman McInnes   Level: advanced
487736851e7fSLois Curfman McInnes 
4878f6dfbefdSBarry Smith   Note:
4879dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
488004edfde5SBarry Smith 
4881e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction`
48829b94acceSBarry Smith @*/
4883d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4884d71ae5a4SJacob Faibussowitsch {
48856cab3a1bSJed Brown   DM dm;
4886a63bb30eSJed Brown 
48873a40ed3dSBarry Smith   PetscFunctionBegin;
48880700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4889a63bb30eSJed Brown   if (r) {
4890a63bb30eSJed Brown     if (!snes->vec_func) {
4891a63bb30eSJed Brown       if (snes->vec_rhs) {
48929566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
4893a63bb30eSJed Brown       } else if (snes->vec_sol) {
48949566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
4895a63bb30eSJed Brown       } else if (snes->dm) {
48969566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
4897a63bb30eSJed Brown       }
4898a63bb30eSJed Brown     }
4899a63bb30eSJed Brown     *r = snes->vec_func;
4900a63bb30eSJed Brown   }
49019566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49029566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
49033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49049b94acceSBarry Smith }
49059b94acceSBarry Smith 
4906c79ef259SPeter Brune /*@C
490737fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
4908c79ef259SPeter Brune 
4909c79ef259SPeter Brune   Input Parameter:
4910f6dfbefdSBarry Smith . snes - the `SNES` context
4911c79ef259SPeter Brune 
4912d8d19677SJose E. Roman   Output Parameters:
491337fdd005SBarry Smith + f   - the function (or `NULL`) see `SNESSetNGS()` for details
4914dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
4915c79ef259SPeter Brune 
4916c79ef259SPeter Brune   Level: advanced
4917c79ef259SPeter Brune 
49181cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`
4919c79ef259SPeter Brune @*/
4920d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4921d71ae5a4SJacob Faibussowitsch {
49226cab3a1bSJed Brown   DM dm;
49236cab3a1bSJed Brown 
4924646217ecSPeter Brune   PetscFunctionBegin;
4925646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49269566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49279566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
49283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4929646217ecSPeter Brune }
4930646217ecSPeter Brune 
49313c7409f5SSatish Balay /*@C
49323c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
4933f6dfbefdSBarry Smith   `SNES` options in the database.
49343c7409f5SSatish Balay 
4935c3339decSBarry Smith   Logically Collective
4936fee21e36SBarry Smith 
4937d8d19677SJose E. Roman   Input Parameters:
4938f6dfbefdSBarry Smith + snes   - the `SNES` context
4939c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
4940c7afd0dbSLois Curfman McInnes 
4941dc4c0fb0SBarry Smith   Level: advanced
4942dc4c0fb0SBarry Smith 
4943f6dfbefdSBarry Smith   Note:
4944a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
4945c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
4946d850072dSLois Curfman McInnes 
49471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
49483c7409f5SSatish Balay @*/
4949d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
4950d71ae5a4SJacob Faibussowitsch {
49513a40ed3dSBarry Smith   PetscFunctionBegin;
49520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49539566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
49549566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
495535f5d045SPeter Brune   if (snes->linesearch) {
49569566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
49579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
495835f5d045SPeter Brune   }
49599566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
49603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49613c7409f5SSatish Balay }
49623c7409f5SSatish Balay 
49633c7409f5SSatish Balay /*@C
4964f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
4965f6dfbefdSBarry Smith   `SNES` options in the database.
49663c7409f5SSatish Balay 
4967c3339decSBarry Smith   Logically Collective
4968fee21e36SBarry Smith 
4969c7afd0dbSLois Curfman McInnes   Input Parameters:
4970f6dfbefdSBarry Smith + snes   - the `SNES` context
4971c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
4972c7afd0dbSLois Curfman McInnes 
4973dc4c0fb0SBarry Smith   Level: advanced
4974dc4c0fb0SBarry Smith 
4975f6dfbefdSBarry Smith   Note:
4976a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
4977c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
4978d850072dSLois Curfman McInnes 
49791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
49803c7409f5SSatish Balay @*/
4981d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
4982d71ae5a4SJacob Faibussowitsch {
49833a40ed3dSBarry Smith   PetscFunctionBegin;
49840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49859566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
49869566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
498735f5d045SPeter Brune   if (snes->linesearch) {
49889566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
49899566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
499035f5d045SPeter Brune   }
49919566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
49923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49933c7409f5SSatish Balay }
49943c7409f5SSatish Balay 
49959ab63eb5SSatish Balay /*@C
4996f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
4997f6dfbefdSBarry Smith   `SNES` options in the database.
49983c7409f5SSatish Balay 
4999c7afd0dbSLois Curfman McInnes   Not Collective
5000c7afd0dbSLois Curfman McInnes 
50013c7409f5SSatish Balay   Input Parameter:
5002f6dfbefdSBarry Smith . snes - the `SNES` context
50033c7409f5SSatish Balay 
50043c7409f5SSatish Balay   Output Parameter:
50053c7409f5SSatish Balay . prefix - pointer to the prefix string used
50063c7409f5SSatish Balay 
500736851e7fSLois Curfman McInnes   Level: advanced
500836851e7fSLois Curfman McInnes 
5009e4094ef1SJacob Faibussowitsch   Fortran Notes:
5010dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5011dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5012dc4c0fb0SBarry Smith 
50131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
50143c7409f5SSatish Balay @*/
5015d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5016d71ae5a4SJacob Faibussowitsch {
50173a40ed3dSBarry Smith   PetscFunctionBegin;
50180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50199566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
50203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50213c7409f5SSatish Balay }
50223c7409f5SSatish Balay 
50233cea93caSBarry Smith /*@C
50241c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
50251c84c290SBarry Smith 
502620f4b53cSBarry Smith   Not Collective
50271c84c290SBarry Smith 
50281c84c290SBarry Smith   Input Parameters:
502920f4b53cSBarry Smith + sname    - name of a new user-defined solver
503020f4b53cSBarry Smith - function - routine to create method context
50311c84c290SBarry Smith 
5032dc4c0fb0SBarry Smith   Level: advanced
5033dc4c0fb0SBarry Smith 
5034f6dfbefdSBarry Smith   Note:
5035f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
50361c84c290SBarry Smith 
5037e4094ef1SJacob Faibussowitsch   Example Usage:
50381c84c290SBarry Smith .vb
5039bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
50401c84c290SBarry Smith .ve
50411c84c290SBarry Smith 
50421c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
50431c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
50441c84c290SBarry Smith   or at runtime via the option
50451c84c290SBarry Smith $     -snes_type my_solver
50461c84c290SBarry Smith 
50471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
50483cea93caSBarry Smith @*/
5049d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5050d71ae5a4SJacob Faibussowitsch {
5051b2002411SLois Curfman McInnes   PetscFunctionBegin;
50529566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
50539566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
50543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5055b2002411SLois Curfman McInnes }
5056da9b6338SBarry Smith 
5057d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5058d71ae5a4SJacob Faibussowitsch {
505977431f27SBarry Smith   PetscInt    N, i, j;
5060da9b6338SBarry Smith   Vec         u, uh, fh;
5061da9b6338SBarry Smith   PetscScalar value;
5062da9b6338SBarry Smith   PetscReal   norm;
5063da9b6338SBarry Smith 
5064da9b6338SBarry Smith   PetscFunctionBegin;
50659566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
50669566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
50679566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5068da9b6338SBarry Smith 
5069da9b6338SBarry Smith   /* currently only works for sequential */
50709566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
50719566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5072da9b6338SBarry Smith   for (i = 0; i < N; i++) {
50739566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
507463a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5075da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
50768b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
50779566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
50789566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
50799566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
508063a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5081da9b6338SBarry Smith       value = -value;
50829566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5083da9b6338SBarry Smith     }
5084da9b6338SBarry Smith   }
50859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
50869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
50873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5088da9b6338SBarry Smith }
508971f87433Sdalcinl 
509071f87433Sdalcinl /*@
5091f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
509271f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
509371f87433Sdalcinl   Newton method.
509471f87433Sdalcinl 
5095c3339decSBarry Smith   Logically Collective
509671f87433Sdalcinl 
509771f87433Sdalcinl   Input Parameters:
5098f6dfbefdSBarry Smith + snes - `SNES` context
5099f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
510071f87433Sdalcinl 
5101f6dfbefdSBarry Smith   Options Database Keys:
510264ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
510364ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
510464ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
510564ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
510664ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
510764ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
510864ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
510964ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
511064ba62caSBarry Smith 
5111dc4c0fb0SBarry Smith   Level: advanced
5112dc4c0fb0SBarry Smith 
5113f6dfbefdSBarry Smith   Note:
5114f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
511571f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
511671f87433Sdalcinl   Eisenstat-Walker method, where the relative convergence tolerance
511771f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
511871f87433Sdalcinl   solver.
511971f87433Sdalcinl 
5120e4094ef1SJacob Faibussowitsch   References:
5121f6dfbefdSBarry Smith .  - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996.
512271f87433Sdalcinl 
51231cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
512471f87433Sdalcinl @*/
5125d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5126d71ae5a4SJacob Faibussowitsch {
512771f87433Sdalcinl   PetscFunctionBegin;
51280700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5129acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
513071f87433Sdalcinl   snes->ksp_ewconv = flag;
51313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
513271f87433Sdalcinl }
513371f87433Sdalcinl 
513471f87433Sdalcinl /*@
5135f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
513671f87433Sdalcinl   for computing relative tolerance for linear solvers within an
513771f87433Sdalcinl   inexact Newton method.
513871f87433Sdalcinl 
513971f87433Sdalcinl   Not Collective
514071f87433Sdalcinl 
514171f87433Sdalcinl   Input Parameter:
5142f6dfbefdSBarry Smith . snes - `SNES` context
514371f87433Sdalcinl 
514471f87433Sdalcinl   Output Parameter:
5145f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
514671f87433Sdalcinl 
514771f87433Sdalcinl   Level: advanced
514871f87433Sdalcinl 
51491cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
515071f87433Sdalcinl @*/
5151d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5152d71ae5a4SJacob Faibussowitsch {
515371f87433Sdalcinl   PetscFunctionBegin;
51540700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5155534a8f05SLisandro Dalcin   PetscValidBoolPointer(flag, 2);
515671f87433Sdalcinl   *flag = snes->ksp_ewconv;
51573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515871f87433Sdalcinl }
515971f87433Sdalcinl 
516071f87433Sdalcinl /*@
5161fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
516271f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
516371f87433Sdalcinl   Newton method.
516471f87433Sdalcinl 
5165c3339decSBarry Smith   Logically Collective
516671f87433Sdalcinl 
516771f87433Sdalcinl   Input Parameters:
5168f6dfbefdSBarry Smith + snes      - `SNES` context
51690f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
517071f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
517171f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
517271f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
517371f87433Sdalcinl              (0 <= gamma2 <= 1)
517471f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
517571f87433Sdalcinl . alpha2    - power for safeguard
517671f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
517771f87433Sdalcinl 
5178dc4c0fb0SBarry Smith   Level: advanced
5179dc4c0fb0SBarry Smith 
5180f6dfbefdSBarry Smith   Notes:
518171f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
518271f87433Sdalcinl 
5183f6dfbefdSBarry Smith   Use `PETSC_DEFAULT` to retain the default for any of the parameters.
518471f87433Sdalcinl 
51851cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
518671f87433Sdalcinl @*/
5187d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5188d71ae5a4SJacob Faibussowitsch {
5189fa9f3622SBarry Smith   SNESKSPEW *kctx;
51905fd66863SKarl Rupp 
519171f87433Sdalcinl   PetscFunctionBegin;
51920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5193fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
51945f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5195c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5196c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5197c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5198c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5199c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5200c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5201c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
520271f87433Sdalcinl 
520371f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
520413bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
520513bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
520613bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
520713bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
520813bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
520913bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
521071f87433Sdalcinl 
52110f0abf79SStefano 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);
52120b121fc5SBarry 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);
52130b121fc5SBarry 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);
52140b121fc5SBarry 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);
52150b121fc5SBarry 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);
52160b121fc5SBarry 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);
52173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
521871f87433Sdalcinl }
521971f87433Sdalcinl 
522071f87433Sdalcinl /*@
5221fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
522271f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
522371f87433Sdalcinl   Newton method.
522471f87433Sdalcinl 
522571f87433Sdalcinl   Not Collective
522671f87433Sdalcinl 
522797bb3fdcSJose E. Roman   Input Parameter:
5228f6dfbefdSBarry Smith . snes - `SNES` context
522971f87433Sdalcinl 
523071f87433Sdalcinl   Output Parameters:
52310f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
523271f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
523371f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5234bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
523571f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
523671f87433Sdalcinl . alpha2    - power for safeguard
523771f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
523871f87433Sdalcinl 
523971f87433Sdalcinl   Level: advanced
524071f87433Sdalcinl 
52411cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
524271f87433Sdalcinl @*/
5243d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5244d71ae5a4SJacob Faibussowitsch {
5245fa9f3622SBarry Smith   SNESKSPEW *kctx;
52465fd66863SKarl Rupp 
524771f87433Sdalcinl   PetscFunctionBegin;
52480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5249fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52505f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
525171f87433Sdalcinl   if (version) *version = kctx->version;
525271f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
525371f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
525471f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
525571f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
525671f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
525771f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
52583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
525971f87433Sdalcinl }
526071f87433Sdalcinl 
5261d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5262d71ae5a4SJacob Faibussowitsch {
5263fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
526471f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
526571f87433Sdalcinl 
526671f87433Sdalcinl   PetscFunctionBegin;
52673ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
526830058271SDmitry Karpeev   if (!snes->iter) {
526930058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
52709566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
52710f0abf79SStefano Zampini   } else {
52720fdf79fbSJacob 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);
527371f87433Sdalcinl     if (kctx->version == 1) {
52740f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
527585ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
527671f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
527771f87433Sdalcinl     } else if (kctx->version == 2) {
527885ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
527985ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
528071f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
528171f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
528285ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
528371f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
528485ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
528571f87433Sdalcinl       stol = PetscMax(rtol, stol);
528671f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
528771f87433Sdalcinl       /* safeguard: avoid oversolving */
528830058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
528971f87433Sdalcinl       stol = PetscMax(rtol, stol);
529071f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
52910fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
52920fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
52930f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
52940f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
52950f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
52960f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
52970f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
52980f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
52990f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
53000f0abf79SStefano Zampini 
5301a4598233SStefano 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;
53020f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
53030f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
53040f0abf79SStefano Zampini       kctx->rk_last     = rk;
53050fdf79fbSJacob Faibussowitsch     }
53060f0abf79SStefano Zampini   }
53070f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
530871f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
53099566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
531063a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
53113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
531271f87433Sdalcinl }
531371f87433Sdalcinl 
5314d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5315d71ae5a4SJacob Faibussowitsch {
5316fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
531771f87433Sdalcinl   PCSide     pcside;
531871f87433Sdalcinl   Vec        lres;
531971f87433Sdalcinl 
532071f87433Sdalcinl   PetscFunctionBegin;
53213ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
53229566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
532371dbe336SPeter Brune   kctx->norm_last = snes->norm;
53240f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
53254f00ce20SMatthew G. Knepley     PC        pc;
53260f0abf79SStefano Zampini     PetscBool getRes;
53274f00ce20SMatthew G. Knepley 
53289566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
53290f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
53300f0abf79SStefano Zampini     if (!getRes) {
53310f0abf79SStefano Zampini       KSPNormType normtype;
53320f0abf79SStefano Zampini 
53330f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
53340f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
53350f0abf79SStefano Zampini     }
53369566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
53370f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
53389566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
533971f87433Sdalcinl     } else {
534071f87433Sdalcinl       /* KSP residual is preconditioned residual */
534171f87433Sdalcinl       /* compute true linear residual norm */
53420f0abf79SStefano Zampini       Mat J;
53430f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
53449566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
53450f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
53469566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
53479566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
53489566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
534971f87433Sdalcinl     }
535071f87433Sdalcinl   }
53513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
535271f87433Sdalcinl }
535371f87433Sdalcinl 
5354d4211eb9SBarry Smith /*@
5355f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5356d4211eb9SBarry Smith 
5357f6dfbefdSBarry Smith   Not Collective, but if snes is parallel, then ksp is parallel
5358d4211eb9SBarry Smith 
5359d4211eb9SBarry Smith   Input Parameter:
5360f6dfbefdSBarry Smith . snes - the `SNES` context
5361d4211eb9SBarry Smith 
5362d4211eb9SBarry Smith   Output Parameter:
5363f6dfbefdSBarry Smith . ksp - the `KSP` context
5364d4211eb9SBarry Smith 
5365dc4c0fb0SBarry Smith   Level: beginner
5366dc4c0fb0SBarry Smith 
5367d4211eb9SBarry Smith   Notes:
5368f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5369d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5370f6dfbefdSBarry Smith   `PC` contexts as well.
5371f6dfbefdSBarry Smith 
5372f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5373d4211eb9SBarry Smith 
53741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5375d4211eb9SBarry Smith @*/
5376d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5377d71ae5a4SJacob Faibussowitsch {
537871f87433Sdalcinl   PetscFunctionBegin;
5379d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5380d4211eb9SBarry Smith   PetscValidPointer(ksp, 2);
5381d4211eb9SBarry Smith 
5382d4211eb9SBarry Smith   if (!snes->ksp) {
53839566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
53849566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5385d4211eb9SBarry Smith 
53869566063dSJacob Faibussowitsch     PetscCall(KSPSetPreSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_SNESEW, snes));
53879566063dSJacob Faibussowitsch     PetscCall(KSPSetPostSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_SNESEW, snes));
5388a5c2985bSBarry Smith 
53899566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
53909566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5391d4211eb9SBarry Smith   }
5392d4211eb9SBarry Smith   *ksp = snes->ksp;
53933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
539471f87433Sdalcinl }
53956c699258SBarry Smith 
5396af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
53976c699258SBarry Smith /*@
5398f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
53996c699258SBarry Smith 
5400c3339decSBarry Smith   Logically Collective
54016c699258SBarry Smith 
54026c699258SBarry Smith   Input Parameters:
54032a808120SBarry Smith + snes - the nonlinear solver context
5404dc4c0fb0SBarry Smith - dm   - the dm, cannot be `NULL`
5405dc4c0fb0SBarry Smith 
5406dc4c0fb0SBarry Smith   Level: intermediate
54076c699258SBarry Smith 
5408f6dfbefdSBarry Smith   Note:
5409f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5410f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5411e03a659cSJed Brown   problems using the same function space.
5412e03a659cSJed Brown 
54131cc06b55SBarry Smith .seealso: [](ch_snes), `DM`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
54146c699258SBarry Smith @*/
5415d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5416d71ae5a4SJacob Faibussowitsch {
5417345fed2cSBarry Smith   KSP    ksp;
5418942e3340SBarry Smith   DMSNES sdm;
54196c699258SBarry Smith 
54206c699258SBarry Smith   PetscFunctionBegin;
54210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54222a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
54239566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5424942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
542551f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
54269566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
54279566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5428f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
54296cab3a1bSJed Brown     }
54309566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
54319566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
54326cab3a1bSJed Brown   }
54336c699258SBarry Smith   snes->dm     = dm;
5434116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5435f5af7f23SKarl Rupp 
54369566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
54379566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
54389566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5439efd4aadfSBarry Smith   if (snes->npc) {
54409566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
54419566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
54422c155ee1SBarry Smith   }
54433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54446c699258SBarry Smith }
54456c699258SBarry Smith 
54466c699258SBarry Smith /*@
5447f6dfbefdSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some preconditioners
54486c699258SBarry Smith 
5449f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
54506c699258SBarry Smith 
54516c699258SBarry Smith   Input Parameter:
54526c699258SBarry Smith . snes - the preconditioner context
54536c699258SBarry Smith 
54546c699258SBarry Smith   Output Parameter:
54556c699258SBarry Smith . dm - the dm
54566c699258SBarry Smith 
54576c699258SBarry Smith   Level: intermediate
54586c699258SBarry Smith 
54591cc06b55SBarry Smith .seealso: [](ch_snes), `DM`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
54606c699258SBarry Smith @*/
5461d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5462d71ae5a4SJacob Faibussowitsch {
54636c699258SBarry Smith   PetscFunctionBegin;
54640700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54656cab3a1bSJed Brown   if (!snes->dm) {
54669566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5467116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
54686cab3a1bSJed Brown   }
54696c699258SBarry Smith   *dm = snes->dm;
54703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54716c699258SBarry Smith }
54720807856dSBarry Smith 
547331823bd8SMatthew G Knepley /*@
5474be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
547531823bd8SMatthew G Knepley 
5476c3339decSBarry Smith   Collective
547731823bd8SMatthew G Knepley 
547831823bd8SMatthew G Knepley   Input Parameters:
5479f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5480f6dfbefdSBarry Smith - npc  - the preconditioner object
548131823bd8SMatthew G Knepley 
5482dc4c0fb0SBarry Smith   Level: developer
5483dc4c0fb0SBarry Smith 
548431823bd8SMatthew G Knepley   Notes:
5485f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
548631823bd8SMatthew G Knepley   to configure it using the API).
548731823bd8SMatthew G Knepley 
5488f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5489f6dfbefdSBarry Smith 
54901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
549131823bd8SMatthew G Knepley @*/
5492d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5493d71ae5a4SJacob Faibussowitsch {
549431823bd8SMatthew G Knepley   PetscFunctionBegin;
549531823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5496f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5497f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5498f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
54999566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5500f6dfbefdSBarry Smith   snes->npc = npc;
55013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
550231823bd8SMatthew G Knepley }
550331823bd8SMatthew G Knepley 
550431823bd8SMatthew G Knepley /*@
5505f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
550631823bd8SMatthew G Knepley 
5507f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
550831823bd8SMatthew G Knepley 
550931823bd8SMatthew G Knepley   Input Parameter:
5510f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
551131823bd8SMatthew G Knepley 
551231823bd8SMatthew G Knepley   Output Parameter:
5513e4094ef1SJacob Faibussowitsch . pc - preconditioner context
551431823bd8SMatthew G Knepley 
5515f6dfbefdSBarry Smith   Options Database Key:
5516f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5517b5badacbSBarry Smith 
5518dc4c0fb0SBarry Smith   Level: developer
5519dc4c0fb0SBarry Smith 
552095452b02SPatrick Sanan   Notes:
5521f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5522be95d8f1SBarry Smith 
5523f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5524f6dfbefdSBarry Smith   `SNES`
5525951fe5abSBarry Smith 
55261cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
552731823bd8SMatthew G Knepley @*/
5528d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5529d71ae5a4SJacob Faibussowitsch {
5530a64e098fSPeter Brune   const char *optionsprefix;
553131823bd8SMatthew G Knepley 
553231823bd8SMatthew G Knepley   PetscFunctionBegin;
553331823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
553431823bd8SMatthew G Knepley   PetscValidPointer(pc, 2);
5535efd4aadfSBarry Smith   if (!snes->npc) {
5536ec785e5bSStefano Zampini     void *ctx;
5537ec785e5bSStefano Zampini 
55389566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
55399566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
55409566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
55419566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
55429566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5543ec785e5bSStefano Zampini     PetscCall(SNESGetApplicationContext(snes, &ctx));
5544ec785e5bSStefano Zampini     PetscCall(SNESSetApplicationContext(snes->npc, ctx));
55459566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
554631823bd8SMatthew G Knepley   }
5547efd4aadfSBarry Smith   *pc = snes->npc;
55483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
554931823bd8SMatthew G Knepley }
555031823bd8SMatthew G Knepley 
55513ad1a0b9SPatrick Farrell /*@
55523ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
55533ad1a0b9SPatrick Farrell 
55543ad1a0b9SPatrick Farrell   Not Collective
55553ad1a0b9SPatrick Farrell 
55563ad1a0b9SPatrick Farrell   Input Parameter:
5557f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
55583ad1a0b9SPatrick Farrell 
55593ad1a0b9SPatrick Farrell   Output Parameter:
5560f6dfbefdSBarry Smith . has_npc - whether the `SNES` has an NPC or not
55613ad1a0b9SPatrick Farrell 
55623ad1a0b9SPatrick Farrell   Level: developer
55633ad1a0b9SPatrick Farrell 
55641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
55653ad1a0b9SPatrick Farrell @*/
5566d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5567d71ae5a4SJacob Faibussowitsch {
55683ad1a0b9SPatrick Farrell   PetscFunctionBegin;
55693ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5570efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
55713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55723ad1a0b9SPatrick Farrell }
55733ad1a0b9SPatrick Farrell 
5574c40d0f55SPeter Brune /*@
5575be95d8f1SBarry Smith   SNESSetNPCSide - Sets the preconditioning side.
5576c40d0f55SPeter Brune 
5577c3339decSBarry Smith   Logically Collective
5578c40d0f55SPeter Brune 
5579c40d0f55SPeter Brune   Input Parameter:
5580f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5581c40d0f55SPeter Brune 
5582c40d0f55SPeter Brune   Output Parameter:
5583c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5584c40d0f55SPeter Brune .vb
55852d547940SBarry Smith       PC_LEFT - left preconditioning
55862d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5587c40d0f55SPeter Brune .ve
5588c40d0f55SPeter Brune 
5589f6dfbefdSBarry Smith   Options Database Key:
559067b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5591c40d0f55SPeter Brune 
5592dc4c0fb0SBarry Smith   Level: intermediate
5593dc4c0fb0SBarry Smith 
5594f6dfbefdSBarry Smith   Note:
5595f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
55962d547940SBarry Smith 
55971cc06b55SBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`
5598c40d0f55SPeter Brune @*/
5599d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5600d71ae5a4SJacob Faibussowitsch {
5601c40d0f55SPeter Brune   PetscFunctionBegin;
5602c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5603c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5604b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
560554c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5606efd4aadfSBarry Smith   snes->npcside = side;
56073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5608c40d0f55SPeter Brune }
5609c40d0f55SPeter Brune 
5610c40d0f55SPeter Brune /*@
5611be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5612c40d0f55SPeter Brune 
5613c40d0f55SPeter Brune   Not Collective
5614c40d0f55SPeter Brune 
5615c40d0f55SPeter Brune   Input Parameter:
5616f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5617c40d0f55SPeter Brune 
5618c40d0f55SPeter Brune   Output Parameter:
5619c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5620c40d0f55SPeter Brune .vb
5621f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5622f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5623c40d0f55SPeter Brune .ve
5624c40d0f55SPeter Brune 
5625c40d0f55SPeter Brune   Level: intermediate
5626c40d0f55SPeter Brune 
56271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`
5628c40d0f55SPeter Brune @*/
5629d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5630d71ae5a4SJacob Faibussowitsch {
5631c40d0f55SPeter Brune   PetscFunctionBegin;
5632c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5633c40d0f55SPeter Brune   PetscValidPointer(side, 2);
5634efd4aadfSBarry Smith   *side = snes->npcside;
56353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5636c40d0f55SPeter Brune }
5637c40d0f55SPeter Brune 
56389e764e56SPeter Brune /*@
5639f6dfbefdSBarry Smith   SNESSetLineSearch - Sets the linesearch on the `SNES` instance.
56409e764e56SPeter Brune 
5641c3339decSBarry Smith   Collective
56429e764e56SPeter Brune 
56439e764e56SPeter Brune   Input Parameters:
5644f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
56459e764e56SPeter Brune - linesearch - the linesearch object
56469e764e56SPeter Brune 
5647dc4c0fb0SBarry Smith   Level: developer
5648dc4c0fb0SBarry Smith 
5649f6dfbefdSBarry Smith   Note:
5650f6dfbefdSBarry Smith   Use `SNESGetLineSearch()` to retrieve the preconditioner context (for example,
56519e764e56SPeter Brune   to configure it using the API).
56529e764e56SPeter Brune 
56531cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLineSearch()`
56549e764e56SPeter Brune @*/
5655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5656d71ae5a4SJacob Faibussowitsch {
56579e764e56SPeter Brune   PetscFunctionBegin;
56589e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5659f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
56609e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
56619566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
56629566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5663f5af7f23SKarl Rupp 
56649e764e56SPeter Brune   snes->linesearch = linesearch;
5665f5af7f23SKarl Rupp 
56663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56679e764e56SPeter Brune }
56689e764e56SPeter Brune 
5669a34ceb2aSJed Brown /*@
5670dc4c0fb0SBarry Smith   SNESGetLineSearch - Returns the line search context set with `SNESSetLineSearch()`
5671f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
56729e764e56SPeter Brune 
56739e764e56SPeter Brune   Not Collective
56749e764e56SPeter Brune 
56759e764e56SPeter Brune   Input Parameter:
5676f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56779e764e56SPeter Brune 
56789e764e56SPeter Brune   Output Parameter:
56799e764e56SPeter Brune . linesearch - linesearch context
56809e764e56SPeter Brune 
5681162e0bf5SPeter Brune   Level: beginner
56829e764e56SPeter Brune 
56831cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
56849e764e56SPeter Brune @*/
5685d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5686d71ae5a4SJacob Faibussowitsch {
56879e764e56SPeter Brune   const char *optionsprefix;
56889e764e56SPeter Brune 
56899e764e56SPeter Brune   PetscFunctionBegin;
56909e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56919e764e56SPeter Brune   PetscValidPointer(linesearch, 2);
56929e764e56SPeter Brune   if (!snes->linesearch) {
56939566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
56949566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
56959566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
56969566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
56979566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
56989e764e56SPeter Brune   }
56999e764e56SPeter Brune   *linesearch = snes->linesearch;
57003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57019e764e56SPeter Brune }
5702