xref: /petsc/src/snes/interface/snes.c (revision ced0f3ae9b31eb98468b6be6394bef1b1e5bcd8a)
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 
127*ced0f3aeSBarry Smith    Notes:
128*ced0f3aeSBarry Smith    If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
129*ced0f3aeSBarry Smith 
130*ced0f3aeSBarry Smith    You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
131*ced0f3aeSBarry 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()`,
136*ced0f3aeSBarry 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 
157*ced0f3aeSBarry Smith    Notes:
158*ced0f3aeSBarry Smith    If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
159*ced0f3aeSBarry Smith 
160*ced0f3aeSBarry Smith    You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
161*ced0f3aeSBarry 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()`,
166*ced0f3aeSBarry 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:
280f6dfbefdSBarry Smith + newdm - 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()`
836db781477SPatrick Sanan           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
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 
1219f6dfbefdSBarry Smith    Fortran Note:
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 
1251dc4c0fb0SBarry Smith    Fortran Note:
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 
17011cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNES`, `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
1866e4ed7901SPeter Brune    SNESSetInitialFunction - Sets the function vector to be used as the
1867f6dfbefdSBarry Smith    initial function value at the initialization of the method.  In some
1868e4ed7901SPeter Brune    instances, the user has precomputed the function before calling
1869f6dfbefdSBarry Smith    `SNESSolve()`.  This function allows one to avoid a redundant call
1870f6dfbefdSBarry Smith    to `SNESComputeFunction()` in that case.
1871e4ed7901SPeter Brune 
1872c3339decSBarry Smith    Logically Collective
1873e4ed7901SPeter Brune 
1874e4ed7901SPeter Brune    Input Parameters:
1875f6dfbefdSBarry Smith +  snes - the `SNES` context
1876e4ed7901SPeter Brune -  f - vector to store function value
1877e4ed7901SPeter Brune 
1878dc4c0fb0SBarry Smith    Level: developer
1879dc4c0fb0SBarry Smith 
1880e4ed7901SPeter Brune    Notes:
1881e4ed7901SPeter Brune    This should not be modified during the solution procedure.
1882e4ed7901SPeter Brune 
1883f6dfbefdSBarry Smith    This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1884e4ed7901SPeter Brune 
18851cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1886e4ed7901SPeter Brune @*/
1887d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1888d71ae5a4SJacob Faibussowitsch {
1889e4ed7901SPeter Brune   Vec vec_func;
1890e4ed7901SPeter Brune 
1891e4ed7901SPeter Brune   PetscFunctionBegin;
1892e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1893e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1894e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1895efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1896902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
18973ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1898902f982fSPeter Brune   }
18999566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19009566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1901f5af7f23SKarl Rupp 
1902217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1904e4ed7901SPeter Brune }
1905e4ed7901SPeter Brune 
1906534ebe21SPeter Brune /*@
1907f6dfbefdSBarry Smith    SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1908f6dfbefdSBarry Smith    of the `SNES` method, when norms are computed in the solving process
1909534ebe21SPeter Brune 
1910c3339decSBarry Smith    Logically Collective
1911534ebe21SPeter Brune 
1912534ebe21SPeter Brune    Input Parameters:
1913f6dfbefdSBarry Smith +  snes - the `SNES` context
1914365a6726SPeter Brune -  normschedule - the frequency of norm computation
1915534ebe21SPeter Brune 
1916517f1916SMatthew G. Knepley    Options Database Key:
191767b8a455SSatish Balay .  -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1918517f1916SMatthew G. Knepley 
1919dc4c0fb0SBarry Smith    Level: advanced
1920dc4c0fb0SBarry Smith 
1921534ebe21SPeter Brune    Notes:
1922f6dfbefdSBarry Smith    Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1923534ebe21SPeter Brune    of the nonlinear function and the taking of its norm at every iteration to
1924534ebe21SPeter Brune    even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1925f6dfbefdSBarry Smith    `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1926534ebe21SPeter Brune    may either be monitored for convergence or not.  As these are often used as nonlinear
1927534ebe21SPeter Brune    preconditioners, monitoring the norm of their error is not a useful enterprise within
1928534ebe21SPeter Brune    their solution.
1929534ebe21SPeter Brune 
19301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1931534ebe21SPeter Brune @*/
1932d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1933d71ae5a4SJacob Faibussowitsch {
1934534ebe21SPeter Brune   PetscFunctionBegin;
1935534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1936365a6726SPeter Brune   snes->normschedule = normschedule;
19373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1938534ebe21SPeter Brune }
1939534ebe21SPeter Brune 
1940534ebe21SPeter Brune /*@
1941f6dfbefdSBarry Smith    SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1942f6dfbefdSBarry Smith    of the `SNES` method.
1943534ebe21SPeter Brune 
1944c3339decSBarry Smith    Logically Collective
1945534ebe21SPeter Brune 
1946534ebe21SPeter Brune    Input Parameters:
1947f6dfbefdSBarry Smith +  snes - the `SNES` context
1948365a6726SPeter Brune -  normschedule - the type of the norm used
1949534ebe21SPeter Brune 
1950534ebe21SPeter Brune    Level: advanced
1951534ebe21SPeter Brune 
19521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1953534ebe21SPeter Brune @*/
1954d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1955d71ae5a4SJacob Faibussowitsch {
1956534ebe21SPeter Brune   PetscFunctionBegin;
1957534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1958365a6726SPeter Brune   *normschedule = snes->normschedule;
19593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1960534ebe21SPeter Brune }
1961534ebe21SPeter Brune 
1962c5ce4427SMatthew G. Knepley /*@
1963c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1964c5ce4427SMatthew G. Knepley 
1965c3339decSBarry Smith   Logically Collective
1966c5ce4427SMatthew G. Knepley 
1967c5ce4427SMatthew G. Knepley   Input Parameters:
1968f6dfbefdSBarry Smith +  snes - the `SNES` context
1969f6dfbefdSBarry Smith -  norm - the value of the norm
1970c5ce4427SMatthew G. Knepley 
1971c5ce4427SMatthew G. Knepley   Level: developer
1972c5ce4427SMatthew G. Knepley 
19731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1974c5ce4427SMatthew G. Knepley @*/
1975d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1976d71ae5a4SJacob Faibussowitsch {
1977c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1978c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1979c5ce4427SMatthew G. Knepley   snes->norm = norm;
19803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1981c5ce4427SMatthew G. Knepley }
1982c5ce4427SMatthew G. Knepley 
1983c5ce4427SMatthew G. Knepley /*@
1984c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
1985c5ce4427SMatthew G. Knepley 
1986c5ce4427SMatthew G. Knepley   Not Collective
1987c5ce4427SMatthew G. Knepley 
1988c5ce4427SMatthew G. Knepley   Input Parameter:
1989f6dfbefdSBarry Smith . snes - the `SNES` context
1990c5ce4427SMatthew G. Knepley 
1991c5ce4427SMatthew G. Knepley   Output Parameter:
1992c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
1993c5ce4427SMatthew G. Knepley 
1994c5ce4427SMatthew G. Knepley   Level: developer
1995c5ce4427SMatthew G. Knepley 
19961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1997c5ce4427SMatthew G. Knepley @*/
1998d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
1999d71ae5a4SJacob Faibussowitsch {
2000c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2001c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2002dadcf809SJacob Faibussowitsch   PetscValidRealPointer(norm, 2);
2003c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2005c5ce4427SMatthew G. Knepley }
2006c5ce4427SMatthew G. Knepley 
2007c1e67a49SFande Kong /*@
2008f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2009c1e67a49SFande Kong 
2010c1e67a49SFande Kong   Not Collective
2011c1e67a49SFande Kong 
2012c1e67a49SFande Kong   Input Parameter:
2013f6dfbefdSBarry Smith . snes - the `SNES` context
2014c1e67a49SFande Kong 
2015c1e67a49SFande Kong   Output Parameter:
2016c1e67a49SFande Kong . ynorm - the last computed update norm
2017c1e67a49SFande Kong 
2018c1e67a49SFande Kong   Level: developer
2019c1e67a49SFande Kong 
2020f6dfbefdSBarry Smith   Note:
2021f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2022f6dfbefdSBarry Smith 
20231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2024c1e67a49SFande Kong @*/
2025d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2026d71ae5a4SJacob Faibussowitsch {
2027c1e67a49SFande Kong   PetscFunctionBegin;
2028c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2029dadcf809SJacob Faibussowitsch   PetscValidRealPointer(ynorm, 2);
2030c1e67a49SFande Kong   *ynorm = snes->ynorm;
20313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2032c1e67a49SFande Kong }
2033c1e67a49SFande Kong 
2034c1e67a49SFande Kong /*@
20354591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2036c1e67a49SFande Kong 
2037c1e67a49SFande Kong   Not Collective
2038c1e67a49SFande Kong 
2039c1e67a49SFande Kong   Input Parameter:
2040f6dfbefdSBarry Smith . snes - the `SNES` context
2041c1e67a49SFande Kong 
2042c1e67a49SFande Kong   Output Parameter:
2043c1e67a49SFande Kong . xnorm - the last computed solution norm
2044c1e67a49SFande Kong 
2045c1e67a49SFande Kong   Level: developer
2046c1e67a49SFande Kong 
20471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2048c1e67a49SFande Kong @*/
2049d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2050d71ae5a4SJacob Faibussowitsch {
2051c1e67a49SFande Kong   PetscFunctionBegin;
2052c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2053dadcf809SJacob Faibussowitsch   PetscValidRealPointer(xnorm, 2);
2054c1e67a49SFande Kong   *xnorm = snes->xnorm;
20553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2056c1e67a49SFande Kong }
2057c1e67a49SFande Kong 
205847073ea2SPeter Brune /*@C
2059f6dfbefdSBarry Smith    SNESSetFunctionType - Sets the `SNESFunctionType`
2060f6dfbefdSBarry Smith    of the `SNES` method.
206147073ea2SPeter Brune 
2062c3339decSBarry Smith    Logically Collective
206347073ea2SPeter Brune 
206447073ea2SPeter Brune    Input Parameters:
2065f6dfbefdSBarry Smith +  snes - the `SNES` context
2066f6dfbefdSBarry Smith -  type - the function type
206747073ea2SPeter Brune 
206847073ea2SPeter Brune    Level: developer
206947073ea2SPeter Brune 
2070f6dfbefdSBarry Smith    Notes:
2071f6dfbefdSBarry Smith    Possible values of the function type
2072f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType`
2073f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2074f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()`
2075f6dfbefdSBarry Smith 
2076f6dfbefdSBarry Smith    Different `SNESType`s use this value in different ways
2077f6dfbefdSBarry Smith 
20781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
207947073ea2SPeter Brune @*/
2080d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2081d71ae5a4SJacob Faibussowitsch {
208247073ea2SPeter Brune   PetscFunctionBegin;
208347073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
208447073ea2SPeter Brune   snes->functype = type;
20853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208647073ea2SPeter Brune }
208747073ea2SPeter Brune 
208847073ea2SPeter Brune /*@C
2089f6dfbefdSBarry Smith    SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
209047073ea2SPeter Brune    of the SNES method.
209147073ea2SPeter Brune 
2092c3339decSBarry Smith    Logically Collective
209347073ea2SPeter Brune 
209447073ea2SPeter Brune    Input Parameters:
2095f6dfbefdSBarry Smith +  snes - the `SNES` context
2096f6dfbefdSBarry Smith -  type - the type of the function evaluation, see `SNESSetFunctionType()`
209747073ea2SPeter Brune 
209847073ea2SPeter Brune    Level: advanced
209947073ea2SPeter Brune 
21001cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
210147073ea2SPeter Brune @*/
2102d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2103d71ae5a4SJacob Faibussowitsch {
210447073ea2SPeter Brune   PetscFunctionBegin;
210547073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
210647073ea2SPeter Brune   *type = snes->functype;
21073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2108534ebe21SPeter Brune }
2109534ebe21SPeter Brune 
2110c79ef259SPeter Brune /*@C
2111be95d8f1SBarry Smith    SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2112c79ef259SPeter Brune    use with composed nonlinear solvers.
2113c79ef259SPeter Brune 
2114c79ef259SPeter Brune    Input Parameters:
2115dc4c0fb0SBarry Smith +  snes   - the `SNES` context
211637fdd005SBarry Smith .  f - function evaluation routine to apply Gauss-Seidel
2117c79ef259SPeter Brune -  ctx    - [optional] user-defined context for private data for the
2118dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2119c79ef259SPeter Brune 
212020f4b53cSBarry Smith    Calling sequence of `f`:
212120f4b53cSBarry Smith $  PetscErrorCode f(SNES snes, Vec X, Vec B, void *ctx)
2122f6dfbefdSBarry Smith +  snes - the `SNES` context
2123f6dfbefdSBarry Smith .  X - the current solution
2124dc4c0fb0SBarry Smith .  B - the right hand side vector (which may be `NULL`)
2125f6dfbefdSBarry Smith -  ctx - a user provided context
2126f6dfbefdSBarry Smith 
2127dc4c0fb0SBarry Smith    Level: intermediate
2128dc4c0fb0SBarry Smith 
2129f6dfbefdSBarry Smith    Note:
2130f6dfbefdSBarry Smith    The `SNESNGS` routines are used by the composed nonlinear solver to generate
2131f6dfbefdSBarry Smith     a problem appropriate update to the solution, particularly `SNESFAS`.
2132c79ef259SPeter Brune 
21331cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`
2134c79ef259SPeter Brune @*/
2135d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNGS(SNES snes, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
2136d71ae5a4SJacob Faibussowitsch {
21376cab3a1bSJed Brown   DM dm;
21386cab3a1bSJed Brown 
2139646217ecSPeter Brune   PetscFunctionBegin;
21406cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21419566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21429566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2144646217ecSPeter Brune }
2145646217ecSPeter Brune 
2146bbc1464cSBarry Smith /*
2147bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2148bbc1464cSBarry Smith    changed during the KSPSolve()
2149bbc1464cSBarry Smith */
2150d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2151d71ae5a4SJacob Faibussowitsch {
2152bbc1464cSBarry Smith   DM     dm;
2153bbc1464cSBarry Smith   DMSNES sdm;
2154bbc1464cSBarry Smith 
2155bbc1464cSBarry Smith   PetscFunctionBegin;
21569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21579566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2158bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2159bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2160792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21619566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21620df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2163ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2164792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21659566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2166bbc1464cSBarry Smith   } else {
2167792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21689566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2169bbc1464cSBarry Smith   }
21703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2171bbc1464cSBarry Smith }
2172bbc1464cSBarry Smith 
2173d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2174d71ae5a4SJacob Faibussowitsch {
2175e03ab78fSPeter Brune   DM     dm;
2176942e3340SBarry Smith   DMSNES sdm;
21776cab3a1bSJed Brown 
21788b0a5094SBarry Smith   PetscFunctionBegin;
21799566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21809566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
21818b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2182bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2183792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21849566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2185792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
21869566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2187bbc1464cSBarry Smith   } else {
2188792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
21899566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2190bbc1464cSBarry Smith   }
21913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21928b0a5094SBarry Smith }
21938b0a5094SBarry Smith 
2194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2195d71ae5a4SJacob Faibussowitsch {
21968b0a5094SBarry Smith   PetscFunctionBegin;
2197e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2198bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
21999566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22009566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22028b0a5094SBarry Smith }
22038b0a5094SBarry Smith 
22048b0a5094SBarry Smith /*@C
2205f6dfbefdSBarry Smith    SNESSetPicard - Use `SNES` to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization)
22068b0a5094SBarry Smith 
2207c3339decSBarry Smith    Logically Collective
22088b0a5094SBarry Smith 
22098b0a5094SBarry Smith    Input Parameters:
2210f6dfbefdSBarry Smith +  snes - the `SNES` context
2211dc4c0fb0SBarry Smith .  r - vector to store function values, may be `NULL`
2212dc4c0fb0SBarry Smith .  bp - function evaluation routine, may be `NULL`
22136b7fb656SBarry Smith .  Amat - matrix with which A(x) x - bp(x) - b is to be computed
2214dc4c0fb0SBarry Smith .  Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
221520f4b53cSBarry Smith .  J  - function to compute matrix values, for the calling sequence see `SNESJacobianFunction()`
2216dc4c0fb0SBarry Smith -  ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2217dc4c0fb0SBarry Smith 
2218dc4c0fb0SBarry Smith    Level: intermediate
22198b0a5094SBarry Smith 
22208b0a5094SBarry Smith    Notes:
22216b7fb656SBarry Smith     It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2222f450aa47SBarry 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.
2223f450aa47SBarry Smith 
2224f6dfbefdSBarry Smith     One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22258b0a5094SBarry Smith 
2226dc4c0fb0SBarry 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}.
2227dc4c0fb0SBarry Smith      When an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration.
22288b0a5094SBarry Smith 
2229dc4c0fb0SBarry Smith      Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22308b0a5094SBarry Smith 
22310d04baf8SBarry Smith    We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22326b7fb656SBarry Smith    the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b
22338b0a5094SBarry Smith 
22348b0a5094SBarry 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
22358b0a5094SBarry 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
22368b0a5094SBarry Smith    different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
22378b0a5094SBarry Smith 
2238dc4c0fb0SBarry 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
2239f6dfbefdSBarry Smith     A(x^{n}) is used to build the preconditioner
22406b7fb656SBarry Smith 
2241dc4c0fb0SBarry 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.
22426b7fb656SBarry Smith 
2243dc4c0fb0SBarry 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
22446b7fb656SBarry 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
2245f6dfbefdSBarry 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`.
2246aaa8cc7dSPierre Jolivet    See the comment in src/snes/tutorials/ex15.c.
2247bbc1464cSBarry Smith 
22481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, `SNESJacobianFunction`
22498b0a5094SBarry Smith @*/
2250d71ae5a4SJacob 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)
2251d71ae5a4SJacob Faibussowitsch {
2252e03ab78fSPeter Brune   DM dm;
2253e03ab78fSPeter Brune 
22548b0a5094SBarry Smith   PetscFunctionBegin;
22558b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22569566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22579566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22589566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22599566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22609566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22628b0a5094SBarry Smith }
22638b0a5094SBarry Smith 
22647971a8bfSPeter Brune /*@C
22657971a8bfSPeter Brune    SNESGetPicard - Returns the context for the Picard iteration
22667971a8bfSPeter Brune 
2267f6dfbefdSBarry Smith    Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
22687971a8bfSPeter Brune 
22697971a8bfSPeter Brune    Input Parameter:
2270f6dfbefdSBarry Smith .  snes - the `SNES` context
22717971a8bfSPeter Brune 
2272d8d19677SJose E. Roman    Output Parameters:
2273dc4c0fb0SBarry Smith +  r - the function (or `NULL`)
227420f4b53cSBarry Smith .  f - the function (or `NULL`);  for calling sequence see `SNESFunction`
2275dc4c0fb0SBarry Smith .  Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2276dc4c0fb0SBarry Smith .  Pmat  - the matrix from which the preconditioner will be constructed (or `NULL`)
227720f4b53cSBarry Smith .  J - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFunction`
2278dc4c0fb0SBarry Smith -  ctx - the function context (or `NULL`)
22797971a8bfSPeter Brune 
22807971a8bfSPeter Brune    Level: advanced
22817971a8bfSPeter Brune 
22821cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunction`, `SNESJacobianFunction`
22837971a8bfSPeter Brune @*/
2284d71ae5a4SJacob 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)
2285d71ae5a4SJacob Faibussowitsch {
22867971a8bfSPeter Brune   DM dm;
22877971a8bfSPeter Brune 
22887971a8bfSPeter Brune   PetscFunctionBegin;
22897971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22909566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
22919566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
22929566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22939566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
22943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22957971a8bfSPeter Brune }
22967971a8bfSPeter Brune 
2297d25893d9SBarry Smith /*@C
2298dc4c0fb0SBarry Smith    SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2299d25893d9SBarry Smith 
2300c3339decSBarry Smith    Logically Collective
2301d25893d9SBarry Smith 
2302d25893d9SBarry Smith    Input Parameters:
2303f6dfbefdSBarry Smith +  snes - the `SNES` context
2304d25893d9SBarry Smith .  func - function evaluation routine
2305d25893d9SBarry Smith -  ctx - [optional] user-defined context for private data for the
2306dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2307d25893d9SBarry Smith 
230820f4b53cSBarry Smith    Calling sequence of `func`:
230920f4b53cSBarry Smith $    PetscErrorCode func(SNES snes, Vec x, void *ctx);
231020f4b53cSBarry Smith +  snes - the `SNES` solver
231120f4b53cSBarry Smith .  x - vector to put initial guess
2312d25893d9SBarry Smith -  ctx - optional user-defined function context
2313d25893d9SBarry Smith 
2314d25893d9SBarry Smith    Level: intermediate
2315d25893d9SBarry Smith 
23161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`
2317d25893d9SBarry Smith @*/
2318d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeInitialGuess(SNES snes, PetscErrorCode (*func)(SNES, Vec, void *), void *ctx)
2319d71ae5a4SJacob Faibussowitsch {
2320d25893d9SBarry Smith   PetscFunctionBegin;
2321d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2322d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2323d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2325d25893d9SBarry Smith }
2326d25893d9SBarry Smith 
23271096aae1SMatthew Knepley /*@C
2328dc4c0fb0SBarry Smith    SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
23291096aae1SMatthew Knepley    it assumes a zero right hand side.
23301096aae1SMatthew Knepley 
2331c3339decSBarry Smith    Logically Collective
23321096aae1SMatthew Knepley 
23331096aae1SMatthew Knepley    Input Parameter:
2334f6dfbefdSBarry Smith .  snes - the `SNES` context
23351096aae1SMatthew Knepley 
23361096aae1SMatthew Knepley    Output Parameter:
2337dc4c0fb0SBarry Smith .  rhs - the right hand side vector or `NULL` if the right hand side vector is null
23381096aae1SMatthew Knepley 
23391096aae1SMatthew Knepley    Level: intermediate
23401096aae1SMatthew Knepley 
23411cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23421096aae1SMatthew Knepley @*/
2343d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2344d71ae5a4SJacob Faibussowitsch {
23451096aae1SMatthew Knepley   PetscFunctionBegin;
23460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23471096aae1SMatthew Knepley   PetscValidPointer(rhs, 2);
234885385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23501096aae1SMatthew Knepley }
23511096aae1SMatthew Knepley 
23529b94acceSBarry Smith /*@
2353f6dfbefdSBarry Smith    SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23549b94acceSBarry Smith 
2355c3339decSBarry Smith    Collective
2356c7afd0dbSLois Curfman McInnes 
23579b94acceSBarry Smith    Input Parameters:
2358f6dfbefdSBarry Smith +  snes - the `SNES` context
2359c7afd0dbSLois Curfman McInnes -  x - input vector
23609b94acceSBarry Smith 
23619b94acceSBarry Smith    Output Parameter:
2362f6dfbefdSBarry Smith .  y - function vector, as set by `SNESSetFunction()`
23639b94acceSBarry Smith 
2364dc4c0fb0SBarry Smith    Level: developer
2365dc4c0fb0SBarry Smith 
2366f6dfbefdSBarry Smith    Note:
2367f6dfbefdSBarry Smith    `SNESComputeFunction()` is typically used within nonlinear solvers
2368bbc1464cSBarry Smith    implementations, so users would not generally call this routine themselves.
236936851e7fSLois Curfman McInnes 
23701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
23719b94acceSBarry Smith @*/
2372d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2373d71ae5a4SJacob Faibussowitsch {
23746cab3a1bSJed Brown   DM     dm;
2375942e3340SBarry Smith   DMSNES sdm;
23769b94acceSBarry Smith 
23773a40ed3dSBarry Smith   PetscFunctionBegin;
23780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23790700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
23800700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2381c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2382c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2383e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2384184914b5SBarry Smith 
23859566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23869566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
23870fdf79fbSJacob 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().");
238832f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
238948a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
23909566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
23918ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
23928ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2393800f99ffSJeremy L Thompson     {
2394800f99ffSJeremy L Thompson       void *ctx;
2395800f99ffSJeremy L Thompson       PetscErrorCode (*computefunction)(SNES, Vec, Vec, void *);
2396800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2397800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2398800f99ffSJeremy L Thompson     }
23999566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
240048a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24010fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24029566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24030fdf79fbSJacob Faibussowitsch   }
24041baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2405ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2406422a814eSBarry Smith   /*
2407422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2408422a814eSBarry Smith      propagate the value to all processes
2409422a814eSBarry Smith   */
24101baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24129b94acceSBarry Smith }
24139b94acceSBarry Smith 
2414c79ef259SPeter Brune /*@
2415f6dfbefdSBarry Smith    SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2416bbc1464cSBarry Smith 
2417c3339decSBarry Smith    Collective
2418bbc1464cSBarry Smith 
2419bbc1464cSBarry Smith    Input Parameters:
2420f6dfbefdSBarry Smith +  snes - the `SNES` context
2421bbc1464cSBarry Smith -  x - input vector
2422bbc1464cSBarry Smith 
2423bbc1464cSBarry Smith    Output Parameter:
2424f6dfbefdSBarry Smith .  y - function vector, as set by `SNESSetMFFunction()`
2425bbc1464cSBarry Smith 
2426dc4c0fb0SBarry Smith    Level: developer
2427dc4c0fb0SBarry Smith 
2428bbc1464cSBarry Smith    Notes:
2429f6dfbefdSBarry Smith    `SNESComputeMFFunction()` is used within the matrix vector products called by the matrix created with `MatCreateSNESMF()`
2430bbc1464cSBarry Smith    so users would not generally call this routine themselves.
2431bbc1464cSBarry Smith 
2432f6dfbefdSBarry Smith     Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with `SNESSolve()`
2433f6dfbefdSBarry Smith     while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2434f6dfbefdSBarry 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.
2435bbc1464cSBarry Smith 
24361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2437bbc1464cSBarry Smith @*/
2438d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2439d71ae5a4SJacob Faibussowitsch {
2440bbc1464cSBarry Smith   DM     dm;
2441bbc1464cSBarry Smith   DMSNES sdm;
2442bbc1464cSBarry Smith 
2443bbc1464cSBarry Smith   PetscFunctionBegin;
2444bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2445bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2446bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2447bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2448bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2449e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2450bbc1464cSBarry Smith 
24519566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24529566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24549566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2455bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2456bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2457792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24589566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2460bbc1464cSBarry Smith   snes->nfuncs++;
2461bbc1464cSBarry Smith   /*
2462bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2463bbc1464cSBarry Smith      propagate the value to all processes
2464bbc1464cSBarry Smith   */
24651baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2467bbc1464cSBarry Smith }
2468bbc1464cSBarry Smith 
2469bbc1464cSBarry Smith /*@
2470f6dfbefdSBarry Smith    SNESComputeNGS - Calls the Gauss-Seidel function that has been set with  `SNESSetNGS()`.
2471c79ef259SPeter Brune 
2472c3339decSBarry Smith    Collective
2473c79ef259SPeter Brune 
2474c79ef259SPeter Brune    Input Parameters:
2475f6dfbefdSBarry Smith +  snes - the `SNES` context
2476c79ef259SPeter Brune .  x - input vector
2477c79ef259SPeter Brune -  b - rhs vector
2478c79ef259SPeter Brune 
2479c79ef259SPeter Brune    Output Parameter:
2480c79ef259SPeter Brune .  x - new solution vector
2481c79ef259SPeter Brune 
2482dc4c0fb0SBarry Smith    Level: developer
2483dc4c0fb0SBarry Smith 
2484f6dfbefdSBarry Smith    Note:
2485f6dfbefdSBarry Smith    `SNESComputeNGS()` is typically used within composed nonlinear solver
2486c79ef259SPeter Brune    implementations, so most users would not generally call this routine
2487c79ef259SPeter Brune    themselves.
2488c79ef259SPeter Brune 
24891cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESSetNGS()`, `SNESComputeFunction()`
2490c79ef259SPeter Brune @*/
2491d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2492d71ae5a4SJacob Faibussowitsch {
24936cab3a1bSJed Brown   DM     dm;
2494942e3340SBarry Smith   DMSNES sdm;
2495646217ecSPeter Brune 
2496646217ecSPeter Brune   PetscFunctionBegin;
2497646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2498064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2499064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2500064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2501064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2502e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25049566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25059566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25060fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25079566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2508792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25099566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2512646217ecSPeter Brune }
2513646217ecSPeter Brune 
2514d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2515d71ae5a4SJacob Faibussowitsch {
251612837594SBarry Smith   Mat               A, B, C, D, jacobian;
2517e885f1abSBarry Smith   Vec               x = snes->vec_sol, f = snes->vec_func;
2518e885f1abSBarry Smith   PetscReal         nrm, gnorm;
251981e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
25200e276705SLisandro Dalcin   MatType           mattype;
2521e885f1abSBarry Smith   PetscInt          m, n, M, N;
2522e885f1abSBarry Smith   void             *functx;
25232cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
25243325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2525e885f1abSBarry Smith   MPI_Comm          comm;
2526e885f1abSBarry Smith   PetscInt          tabs;
252712837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
25283325ff46SBarry Smith   PetscViewerFormat format;
2529e885f1abSBarry Smith 
2530e885f1abSBarry Smith   PetscFunctionBegin;
2531d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
25329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
25339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
25349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
253518d89885SKarl Rupp   if (!complete_print) {
25369566063dSJacob Faibussowitsch     PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
25379566063dSJacob Faibussowitsch     PetscCall(PetscOptionsViewer("-snes_test_jacobian_display", "Display difference between hand-coded and finite difference Jacobians", "None", &mviewer, &format, &complete_print));
253818d89885SKarl Rupp   }
253918d89885SKarl Rupp   /* for compatibility with PETSc 3.9 and older. */
25409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
25419566063dSJacob 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));
2542d0609cedSBarry Smith   PetscOptionsEnd();
25433ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2544e885f1abSBarry Smith 
25459566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
25469566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
25479566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
25489566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
25499566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
255012837594SBarry Smith   if (!complete_print && !directionsprinted) {
25519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
25529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
255312837594SBarry Smith   }
255412837594SBarry Smith   if (!directionsprinted) {
25559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
25569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
255712837594SBarry Smith     directionsprinted = PETSC_TRUE;
2558e885f1abSBarry Smith   }
25591baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2560e885f1abSBarry Smith 
25619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
256212837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
256312837594SBarry Smith   else jacobian = snes->jacobian_pre;
256412837594SBarry Smith 
2565a82339d0SMatthew G. Knepley   if (!x) {
25669566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(jacobian, &x, NULL));
2567a82339d0SMatthew G. Knepley   } else {
25689566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
2569a82339d0SMatthew G. Knepley   }
2570a82339d0SMatthew G. Knepley   if (!f) {
25719566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &f));
2572a82339d0SMatthew G. Knepley   } else {
25739566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)f));
2574a82339d0SMatthew G. Knepley   }
2575a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
25769566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
25779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
25789566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
257912837594SBarry Smith   while (jacobian) {
25802cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
25812cd624f9SStefano Zampini 
25822cd624f9SStefano Zampini     if (istranspose) {
25839566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
25842cd624f9SStefano Zampini       Jsave    = jacobian;
25852cd624f9SStefano Zampini       jacobian = JT;
25862cd624f9SStefano Zampini     }
25879566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
258812837594SBarry Smith     if (flg) {
258912837594SBarry Smith       A = jacobian;
25909566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
259112837594SBarry Smith     } else {
25929566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
259312837594SBarry Smith     }
2594e885f1abSBarry Smith 
25959566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
25969566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
25979566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
25989566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
25999566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
26009566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
26019566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
26029566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
26039566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2604e885f1abSBarry Smith 
26059566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
26069566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
260712837594SBarry Smith 
26089566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
26099566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26109566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
26119566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
26129566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
261312837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
26149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
261512837594SBarry Smith 
2616e885f1abSBarry Smith     if (complete_print) {
26179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
26189566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
26199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
26209566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2621e885f1abSBarry Smith     }
2622e885f1abSBarry Smith 
2623df10fb39SFande Kong     if (threshold_print || complete_print) {
2624e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2625e885f1abSBarry Smith       PetscScalar       *cvals;
2626e885f1abSBarry Smith       const PetscInt    *bcols;
2627e885f1abSBarry Smith       const PetscScalar *bvals;
2628e885f1abSBarry Smith 
26299566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
26309566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
26319566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
26329566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
26339566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
26349566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
26350e276705SLisandro Dalcin 
26369566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26379566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2638e885f1abSBarry Smith 
2639e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
26409566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
26419566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2642e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
264323a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2644e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2645e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2646e885f1abSBarry Smith             cncols += 1;
2647e885f1abSBarry Smith           }
2648e885f1abSBarry Smith         }
264948a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
26509566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
26519566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2652e885f1abSBarry Smith       }
26539566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
26549566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
26559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
26569566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
26579566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2658e885f1abSBarry Smith     }
26599566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
26609566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
26619566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
26622cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
266312837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
266412837594SBarry Smith       jacobian = snes->jacobian_pre;
26659566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
26669371c9d4SSatish Balay     } else jacobian = NULL;
266712837594SBarry Smith   }
26689566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
26691baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
26709566063dSJacob Faibussowitsch   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
26719566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
26723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2673e885f1abSBarry Smith }
2674e885f1abSBarry Smith 
267562fef451SLois Curfman McInnes /*@
2676f6dfbefdSBarry Smith    SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
267762fef451SLois Curfman McInnes 
2678c3339decSBarry Smith    Collective
2679c7afd0dbSLois Curfman McInnes 
268062fef451SLois Curfman McInnes    Input Parameters:
2681f6dfbefdSBarry Smith +  snes - the `SNES` context
2682c7afd0dbSLois Curfman McInnes -  x - input vector
268362fef451SLois Curfman McInnes 
268462fef451SLois Curfman McInnes    Output Parameters:
2685c7afd0dbSLois Curfman McInnes +  A - Jacobian matrix
2686f6dfbefdSBarry Smith -  B - optional matrix for building the preconditioner
2687fee21e36SBarry Smith 
2688e35cf81dSBarry Smith   Options Database Keys:
268967b8a455SSatish Balay +    -snes_lag_preconditioner <lag> - how often to rebuild preconditioner
269067b8a455SSatish Balay .    -snes_lag_jacobian <lag> - how often to rebuild Jacobian
2691455a5933SJed 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.
2692455a5933SJed 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
2693693365a8SJed Brown .    -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2694693365a8SJed Brown .    -snes_compare_explicit_draw  - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2695693365a8SJed Brown .    -snes_compare_explicit_contour  - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
26964c30e9fbSJed Brown .    -snes_compare_operator  - Make the comparison options above use the operator instead of the preconditioning matrix
269794d6a431SBarry Smith .    -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference
2698a5b23f4aSJose E. Roman .    -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences
2699c01495d3SJed Brown .    -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold
2700dc4c0fb0SBarry Smith .    -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2701dc4c0fb0SBarry Smith .    -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2702a5b23f4aSJose E. Roman .    -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences
2703a5b23f4aSJose E. Roman -    -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2704c01495d3SJed Brown 
2705dc4c0fb0SBarry Smith    Level: developer
2706dc4c0fb0SBarry Smith 
2707f6dfbefdSBarry Smith    Note:
270862fef451SLois Curfman McInnes    Most users should not need to explicitly call this routine, as it
270962fef451SLois Curfman McInnes    is used internally within the nonlinear solvers.
271062fef451SLois Curfman McInnes 
2711f6dfbefdSBarry Smith    Developer Note:
2712dc4c0fb0SBarry 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
2713dc4c0fb0SBarry Smith       for with the `SNESType` of test that has been removed.
2714e885f1abSBarry Smith 
27151cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
271662fef451SLois Curfman McInnes @*/
2717d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2718d71ae5a4SJacob Faibussowitsch {
2719ace3abfcSBarry Smith   PetscBool flag;
27206cab3a1bSJed Brown   DM        dm;
2721942e3340SBarry Smith   DMSNES    sdm;
2722e0e3a89bSBarry Smith   KSP       ksp;
27233a40ed3dSBarry Smith 
27243a40ed3dSBarry Smith   PetscFunctionBegin;
27250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
27260700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2727c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2728e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
27299566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
27309566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
27313232da50SPeter Brune 
2732ebd3b9afSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
2733fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2734fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2735f5af7f23SKarl Rupp 
27369566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2737fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
27389566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
27399566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2740ebd3b9afSBarry Smith     if (flag) {
27419566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27429566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2743ebd3b9afSBarry Smith     }
27443ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
274537ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
274663a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
27479566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2748ebd3b9afSBarry Smith     if (flag) {
27499566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27509566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2751ebd3b9afSBarry Smith     }
27523ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2753e35cf81dSBarry Smith   }
2754efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
27559566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27569566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
27573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2758d728fb7dSPeter Brune   }
2759e35cf81dSBarry Smith 
27609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
27619566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2762800f99ffSJeremy L Thompson   {
2763800f99ffSJeremy L Thompson     void *ctx;
2764800f99ffSJeremy L Thompson     PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *);
2765800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2766800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2767800f99ffSJeremy L Thompson   }
27689566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
27699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
277028d58a37SPierre Jolivet 
277128d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
27729566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2773a8054027SBarry Smith 
2774e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
27759566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
27763b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
27779566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
27789566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
27793b4f5425SBarry Smith     snes->lagpreconditioner = -1;
27803b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
27819566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
27829566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
278337ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
278463a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
27859566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2786d1e9a80fSBarry Smith   } else {
27879566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
27889566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2789a8054027SBarry Smith   }
2790a8054027SBarry Smith 
27919566063dSJacob Faibussowitsch   PetscCall(SNESTestJacobian(snes));
27926d84be18SBarry Smith   /* make sure user returned a correct Jacobian and preconditioner */
279394ab13aaSBarry Smith   /* PetscValidHeaderSpecific(A,MAT_CLASSID,3);
279494ab13aaSBarry Smith     PetscValidHeaderSpecific(B,MAT_CLASSID,4);   */
2795693365a8SJed Brown   {
2796693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
27979566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
27989566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
27999566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
28009566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2801693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
28020298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2803693365a8SJed Brown       PetscViewer vdraw, vstdout;
28046b3a5b13SJed Brown       PetscBool   flg;
2805693365a8SJed Brown       if (flag_operator) {
28069566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2807693365a8SJed Brown         Bexp = Bexp_mine;
2808693365a8SJed Brown       } else {
2809693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
28109566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
281194ab13aaSBarry Smith         if (flg) Bexp = B;
2812693365a8SJed Brown         else {
2813693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
28149566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2815693365a8SJed Brown           Bexp = Bexp_mine;
2816693365a8SJed Brown         }
2817693365a8SJed Brown       }
28189566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
28199566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
28209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2821693365a8SJed Brown       if (flag_draw || flag_contour) {
28229566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28239566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28240298fd71SBarry Smith       } else vdraw = NULL;
28259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
28269566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
28279566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
28289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
28299566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
28309566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
28319566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
28329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
28339566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2834693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
28359566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28369566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
28379566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2838693365a8SJed Brown       }
28399566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
28409566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
28419566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
28429566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2843693365a8SJed Brown     }
2844693365a8SJed Brown   }
28454c30e9fbSJed Brown   {
28466719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
28476719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
28489566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
28499566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
28509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
28519566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
28529566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
285327b0f280SBarry Smith     if (flag_threshold) {
28549566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
28559566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
285627b0f280SBarry Smith     }
28576719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
28584c30e9fbSJed Brown       Mat           Bfd;
28594c30e9fbSJed Brown       PetscViewer   vdraw, vstdout;
2860335efc43SPeter Brune       MatColoring   coloring;
28614c30e9fbSJed Brown       ISColoring    iscoloring;
28624c30e9fbSJed Brown       MatFDColoring matfdcoloring;
28634c30e9fbSJed Brown       PetscErrorCode (*func)(SNES, Vec, Vec, void *);
28644c30e9fbSJed Brown       void     *funcctx;
28656719d8e4SJed Brown       PetscReal norm1, norm2, normmax;
28664c30e9fbSJed Brown 
28679566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
28689566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
28699566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
28709566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
28719566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
28729566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
28739566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
28749566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28759566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
28769566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
28774c30e9fbSJed Brown 
28784c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
28799566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
28809566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
28819566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
28829566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
28839566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28849566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
28859566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
28864c30e9fbSJed Brown 
28879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
28884c30e9fbSJed Brown       if (flag_draw || flag_contour) {
28899566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28909566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28910298fd71SBarry Smith       } else vdraw = NULL;
28929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
28939566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
28949566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
28959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
28969566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
28979566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
28989566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
28999566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
29009566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
29019566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
29029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
29039566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29044c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
29059566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29069566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
29079566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
29084c30e9fbSJed Brown       }
29099566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29106719d8e4SJed Brown 
29116719d8e4SJed Brown       if (flag_threshold) {
29126719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
29139566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
29149566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
29156719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
29166719d8e4SJed Brown           const PetscScalar *ba, *ca;
29176719d8e4SJed Brown           const PetscInt    *bj, *cj;
29186719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
29196719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
29209566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
29219566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
29225f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
29236719d8e4SJed Brown           for (j = 0; j < bn; j++) {
29246719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
29256719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
29266719d8e4SJed Brown               maxentrycol = bj[j];
29276719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
29286719d8e4SJed Brown             }
29296719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
29306719d8e4SJed Brown               maxdiffcol = bj[j];
29316719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
29326719d8e4SJed Brown             }
29336719d8e4SJed Brown             if (rdiff > maxrdiff) {
29346719d8e4SJed Brown               maxrdiffcol = bj[j];
29356719d8e4SJed Brown               maxrdiff    = rdiff;
29366719d8e4SJed Brown             }
29376719d8e4SJed Brown           }
29386719d8e4SJed Brown           if (maxrdiff > 1) {
293963a3b9bcSJacob 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));
29406719d8e4SJed Brown             for (j = 0; j < bn; j++) {
29416719d8e4SJed Brown               PetscReal rdiff;
29426719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
294348a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
29446719d8e4SJed Brown             }
294563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
29466719d8e4SJed Brown           }
29479566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
29489566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
29496719d8e4SJed Brown         }
29506719d8e4SJed Brown       }
29519566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29529566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
29534c30e9fbSJed Brown     }
29544c30e9fbSJed Brown   }
29553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29569b94acceSBarry Smith }
29579b94acceSBarry Smith 
2958bf388a1fSBarry Smith /*MC
2959f6dfbefdSBarry Smith     SNESJacobianFunction - Function used by `SNES` to compute the nonlinear Jacobian of the function to be solved by `SNES`
2960bf388a1fSBarry Smith 
2961bf388a1fSBarry Smith      Synopsis:
2962411c0326SBarry Smith      #include "petscsnes.h"
2963411c0326SBarry Smith      PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
2964bf388a1fSBarry Smith 
2965c3339decSBarry Smith      Collective
29661843f636SBarry Smith 
29671843f636SBarry Smith     Input Parameters:
29681843f636SBarry Smith +  x - input vector, the Jacobian is to be computed at this value
2969bf388a1fSBarry Smith -  ctx - [optional] user-defined Jacobian context
2970bf388a1fSBarry Smith 
29711843f636SBarry Smith     Output Parameters:
29721843f636SBarry Smith +  Amat - the matrix that defines the (approximate) Jacobian
2973dc4c0fb0SBarry Smith -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
29741843f636SBarry Smith 
2975878cb397SSatish Balay    Level: intermediate
2976878cb397SSatish Balay 
29771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESSetJacobian()`, `SNESGetJacobian()`
2978bf388a1fSBarry Smith M*/
2979bf388a1fSBarry Smith 
29809b94acceSBarry Smith /*@C
29819b94acceSBarry Smith    SNESSetJacobian - Sets the function to compute Jacobian as well as the
2982044dda88SLois Curfman McInnes    location to store the matrix.
29839b94acceSBarry Smith 
2984c3339decSBarry Smith    Logically Collective
2985c7afd0dbSLois Curfman McInnes 
29869b94acceSBarry Smith    Input Parameters:
2987f6dfbefdSBarry Smith +  snes - the `SNES` context
2988e5d3d808SBarry Smith .  Amat - the matrix that defines the (approximate) Jacobian
2989dc4c0fb0SBarry Smith .  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
2990dc4c0fb0SBarry Smith .  J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFunction` for details
2991c7afd0dbSLois Curfman McInnes -  ctx - [optional] user-defined context for private data for the
2992dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
2993dc4c0fb0SBarry Smith 
2994dc4c0fb0SBarry Smith    Level: beginner
29959b94acceSBarry Smith 
29969b94acceSBarry Smith    Notes:
2997dc4c0fb0SBarry Smith    If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
299816913363SBarry Smith    each matrix.
299916913363SBarry Smith 
3000dc4c0fb0SBarry Smith    If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3001dc4c0fb0SBarry Smith    space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3002895c21f2SBarry Smith 
3003dc4c0fb0SBarry Smith    If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3004f6dfbefdSBarry Smith    must be a `MatFDColoring`.
3005a8a26c1eSJed Brown 
3006c3cc8fd1SJed Brown    Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3007f6dfbefdSBarry Smith    example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3008c3cc8fd1SJed Brown 
30091cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
3010db781477SPatrick Sanan           `SNESSetPicard()`, `SNESJacobianFunction`
30119b94acceSBarry Smith @*/
3012d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx)
3013d71ae5a4SJacob Faibussowitsch {
30146cab3a1bSJed Brown   DM dm;
30153a7fca6bSBarry Smith 
30163a40ed3dSBarry Smith   PetscFunctionBegin;
30170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3018e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3019e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3020e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3021e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
30229566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30239566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3024e5d3d808SBarry Smith   if (Amat) {
30259566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
30269566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3027f5af7f23SKarl Rupp 
3028e5d3d808SBarry Smith     snes->jacobian = Amat;
30293a7fca6bSBarry Smith   }
3030e5d3d808SBarry Smith   if (Pmat) {
30319566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
30329566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3033f5af7f23SKarl Rupp 
3034e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
30353a7fca6bSBarry Smith   }
30363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30379b94acceSBarry Smith }
303862fef451SLois Curfman McInnes 
3039c2aafc4cSSatish Balay /*@C
3040b4fd4287SBarry Smith    SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3041b4fd4287SBarry Smith    provided context for evaluating the Jacobian.
3042b4fd4287SBarry Smith 
3043f6dfbefdSBarry Smith    Not Collective, but `Mat` object will be parallel if `SNES` object is
3044c7afd0dbSLois Curfman McInnes 
3045b4fd4287SBarry Smith    Input Parameter:
3046b4fd4287SBarry Smith .  snes - the nonlinear solver context
3047b4fd4287SBarry Smith 
3048b4fd4287SBarry Smith    Output Parameters:
3049dc4c0fb0SBarry Smith +  Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3050dc4c0fb0SBarry Smith .  Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
305120f4b53cSBarry Smith .  J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFunction`
3052dc4c0fb0SBarry Smith -  ctx - location to stash Jacobian ctx (or `NULL`)
3053fee21e36SBarry Smith 
305436851e7fSLois Curfman McInnes    Level: advanced
305536851e7fSLois Curfman McInnes 
30561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFunction`, `SNESGetFunction()`
3057b4fd4287SBarry Smith @*/
3058d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx)
3059d71ae5a4SJacob Faibussowitsch {
30606cab3a1bSJed Brown   DM dm;
30616cab3a1bSJed Brown 
30623a40ed3dSBarry Smith   PetscFunctionBegin;
30630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3064e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3065e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
30669566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3067800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
30683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3069b4fd4287SBarry Smith }
3070b4fd4287SBarry Smith 
3071d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3072d71ae5a4SJacob Faibussowitsch {
307358b371f3SBarry Smith   DM     dm;
307458b371f3SBarry Smith   DMSNES sdm;
307558b371f3SBarry Smith 
307658b371f3SBarry Smith   PetscFunctionBegin;
30779566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30789566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
307958b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
308058b371f3SBarry Smith     DM        dm;
308158b371f3SBarry Smith     PetscBool isdense, ismf;
308258b371f3SBarry Smith 
30839566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
30849566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
30859566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
308658b371f3SBarry Smith     if (isdense) {
30879566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
308858b371f3SBarry Smith     } else if (!ismf) {
30899566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
309058b371f3SBarry Smith     }
309158b371f3SBarry Smith   }
30923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
309358b371f3SBarry Smith }
309458b371f3SBarry Smith 
30959b94acceSBarry Smith /*@
30969b94acceSBarry Smith    SNESSetUp - Sets up the internal data structures for the later use
3097272ac6f2SLois Curfman McInnes    of a nonlinear solver.
30989b94acceSBarry Smith 
3099c3339decSBarry Smith    Collective
3100fee21e36SBarry Smith 
31012fe279fdSBarry Smith    Input Parameter:
3102f6dfbefdSBarry Smith .  snes - the `SNES` context
3103c7afd0dbSLois Curfman McInnes 
3104dc4c0fb0SBarry Smith    Level: advanced
3105dc4c0fb0SBarry Smith 
3106f6dfbefdSBarry Smith    Note:
3107f6dfbefdSBarry Smith    For basic use of the `SNES` solvers the user need not explicitly call
3108f6dfbefdSBarry Smith    `SNESSetUp()`, since these actions will automatically occur during
3109f6dfbefdSBarry Smith    the call to `SNESSolve()`.  However, if one wishes to control this
3110f6dfbefdSBarry Smith    phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3111f6dfbefdSBarry Smith    and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3112272ac6f2SLois Curfman McInnes 
31131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
31149b94acceSBarry Smith @*/
3115d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3116d71ae5a4SJacob Faibussowitsch {
31176cab3a1bSJed Brown   DM             dm;
3118942e3340SBarry Smith   DMSNES         sdm;
3119c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
31206e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
31219b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
31229b5c1c08SStefano Zampini   Vec            f, fpc;
31239b5c1c08SStefano Zampini   void          *funcctx;
31249b5c1c08SStefano Zampini   void          *jacctx, *appctx;
31259b5c1c08SStefano Zampini   Mat            j, jpre;
31266b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
31276b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
31286e2a1849SPeter Brune   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
3129d1e9a80fSBarry Smith   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
31303a40ed3dSBarry Smith 
31313a40ed3dSBarry Smith   PetscFunctionBegin;
31320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31333ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3134fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
31359b94acceSBarry Smith 
313648a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
313785385478SLisandro Dalcin 
31389566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
313958c9b817SLisandro Dalcin 
31409566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31419566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
31429566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
314358b371f3SBarry Smith 
314448a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3145efd51863SBarry Smith 
314648a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3147b710008aSBarry Smith 
3148d8d34be6SBarry Smith   if (snes->linesearch) {
31499566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
31509566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3151d8d34be6SBarry Smith   }
31529e764e56SPeter Brune 
31539b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3154b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3155172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3156172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3157172a4300SPeter Brune   }
3158d8f46077SPeter Brune 
3159efd4aadfSBarry Smith   if (snes->npc) {
31606e2a1849SPeter Brune     /* copy the DM over */
31619566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31629566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
31636e2a1849SPeter Brune 
31649566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
31659566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
31669566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
31679566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
31689566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
31699566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
31709566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
31719b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
31729566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
31736e2a1849SPeter Brune 
31746e2a1849SPeter Brune     /* copy the function pointers over */
31759566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
31766e2a1849SPeter Brune 
31776e2a1849SPeter Brune     /* default to 1 iteration */
31789566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3179efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
31809566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3181a9936a0cSPeter Brune     } else {
31829566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3183a9936a0cSPeter Brune     }
31849566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
31856e2a1849SPeter Brune 
31866e2a1849SPeter Brune     /* copy the line search context over */
3187d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
31889566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
31899566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
31909566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
31919566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
31929566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
31939566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
31949566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
31956e2a1849SPeter Brune     }
3196d8d34be6SBarry Smith   }
31971baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
319848a46eb9SPierre Jolivet   if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user));
31996e2a1849SPeter Brune 
320037ec4e1aSPeter Brune   snes->jac_iter = 0;
320137ec4e1aSPeter Brune   snes->pre_iter = 0;
320237ec4e1aSPeter Brune 
3203dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
320458c9b817SLisandro Dalcin 
32059566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
320658b371f3SBarry Smith 
3207b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
32086c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3209d8d34be6SBarry Smith       if (snes->linesearch) {
32109566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
32119566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
32126c67d002SPeter Brune       }
32136c67d002SPeter Brune     }
3214d8d34be6SBarry Smith   }
3215fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
32167aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
32173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32189b94acceSBarry Smith }
32199b94acceSBarry Smith 
322037596af1SLisandro Dalcin /*@
3221f6dfbefdSBarry Smith    SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
322237596af1SLisandro Dalcin 
3223c3339decSBarry Smith    Collective
322437596af1SLisandro Dalcin 
322537596af1SLisandro Dalcin    Input Parameter:
3226f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
322737596af1SLisandro Dalcin 
3228d25893d9SBarry Smith    Level: intermediate
3229d25893d9SBarry Smith 
323095452b02SPatrick Sanan    Notes:
3231f6dfbefdSBarry Smith    Call this if you wish to reuse a `SNES` but with different size vectors
323237596af1SLisandro Dalcin 
3233f6dfbefdSBarry Smith    Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3234f6dfbefdSBarry Smith 
32351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
323637596af1SLisandro Dalcin @*/
3237d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3238d71ae5a4SJacob Faibussowitsch {
323937596af1SLisandro Dalcin   PetscFunctionBegin;
324037596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3241d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
32429566063dSJacob Faibussowitsch     PetscCall((*snes->ops->userdestroy)((void **)&snes->user));
32430298fd71SBarry Smith     snes->user = NULL;
3244d25893d9SBarry Smith   }
32451baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
32468a23116dSBarry Smith 
3247dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
32481baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
32499e764e56SPeter Brune 
32501baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
32519e764e56SPeter Brune 
32529566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
32539566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
32549566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
32559566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
32569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
32579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
32589566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
32599566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
32609566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3261f5af7f23SKarl Rupp 
326240fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
326340fdac6aSLawrence Mitchell 
326437596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
326537596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
32663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
326737596af1SLisandro Dalcin }
326837596af1SLisandro Dalcin 
326952baeb72SSatish Balay /*@
3270f6dfbefdSBarry Smith    SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object.
3271c4421ceaSFande Kong 
3272c3339decSBarry Smith    Collective
3273c4421ceaSFande Kong 
3274c4421ceaSFande Kong    Input Parameter:
3275f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
3276c4421ceaSFande Kong 
3277c4421ceaSFande Kong    Level: intermediate
3278c4421ceaSFande Kong 
32791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`
3280c4421ceaSFande Kong @*/
3281d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3282d71ae5a4SJacob Faibussowitsch {
3283c4421ceaSFande Kong   PetscInt i;
3284c4421ceaSFande Kong 
3285c4421ceaSFande Kong   PetscFunctionBegin;
3286c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3287c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
328848a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3289c4421ceaSFande Kong   }
3290c4421ceaSFande Kong   snes->numberreasonviews = 0;
32913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3292c4421ceaSFande Kong }
3293c4421ceaSFande Kong 
32941fb7b255SJunchao Zhang /*@C
32959b94acceSBarry Smith    SNESDestroy - Destroys the nonlinear solver context that was created
3296f6dfbefdSBarry Smith    with `SNESCreate()`.
32979b94acceSBarry Smith 
3298c3339decSBarry Smith    Collective
3299c7afd0dbSLois Curfman McInnes 
33009b94acceSBarry Smith    Input Parameter:
3301f6dfbefdSBarry Smith .  snes - the `SNES` context
33029b94acceSBarry Smith 
330336851e7fSLois Curfman McInnes    Level: beginner
330436851e7fSLois Curfman McInnes 
33051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
33069b94acceSBarry Smith @*/
3307d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3308d71ae5a4SJacob Faibussowitsch {
33093a40ed3dSBarry Smith   PetscFunctionBegin;
33103ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
33116bf464f9SBarry Smith   PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1);
33129371c9d4SSatish Balay   if (--((PetscObject)(*snes))->refct > 0) {
33139371c9d4SSatish Balay     *snes = NULL;
33143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
33159371c9d4SSatish Balay   }
3316d4bb536fSBarry Smith 
33179566063dSJacob Faibussowitsch   PetscCall(SNESReset((*snes)));
33189566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
33196b8b9a38SLisandro Dalcin 
3320e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
33219566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3322dbbe0bcdSBarry Smith   PetscTryTypeMethod((*snes), destroy);
33236d4c513bSLisandro Dalcin 
33249566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
33259566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
33269566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
33279566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
33286b8b9a38SLisandro Dalcin 
33299566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
333048a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
333148a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
33329566063dSJacob Faibussowitsch   PetscCall(SNESMonitorCancel((*snes)));
33339566063dSJacob Faibussowitsch   PetscCall(SNESConvergedReasonViewCancel((*snes)));
33349566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
33353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33369b94acceSBarry Smith }
33379b94acceSBarry Smith 
33389b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
33399b94acceSBarry Smith 
3340a8054027SBarry Smith /*@
3341a8054027SBarry Smith    SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3342a8054027SBarry Smith 
3343c3339decSBarry Smith    Logically Collective
3344a8054027SBarry Smith 
3345a8054027SBarry Smith    Input Parameters:
3346f6dfbefdSBarry Smith +  snes - the `SNES` context
3347d8e291bfSBarry Smith -  lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
33483b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3349a8054027SBarry Smith 
3350a8054027SBarry Smith    Options Database Keys:
335179a4f3cfSmarkadams4 +    -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves
33523d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
335379a4f3cfSmarkadams4 .    -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
33543d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3355a8054027SBarry Smith 
3356a8054027SBarry Smith    Notes:
3357dc4c0fb0SBarry Smith    Level: intermediate
3358dc4c0fb0SBarry Smith 
3359a8054027SBarry Smith    The default is 1
3360f6dfbefdSBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3361d8e291bfSBarry Smith 
3362f6dfbefdSBarry Smith    `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3363a8054027SBarry Smith 
33641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3365f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3366a8054027SBarry Smith @*/
3367d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3368d71ae5a4SJacob Faibussowitsch {
3369a8054027SBarry Smith   PetscFunctionBegin;
33700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33715f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
33725f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3373c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3374a8054027SBarry Smith   snes->lagpreconditioner = lag;
33753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3376a8054027SBarry Smith }
3377a8054027SBarry Smith 
3378efd51863SBarry Smith /*@
3379f6dfbefdSBarry Smith    SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3380efd51863SBarry Smith 
3381c3339decSBarry Smith    Logically Collective
3382efd51863SBarry Smith 
3383efd51863SBarry Smith    Input Parameters:
3384f6dfbefdSBarry Smith +  snes - the `SNES` context
3385efd51863SBarry Smith -  steps - the number of refinements to do, defaults to 0
3386efd51863SBarry Smith 
3387f6dfbefdSBarry Smith    Options Database Key:
338867b8a455SSatish Balay .    -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3389efd51863SBarry Smith 
3390efd51863SBarry Smith    Level: intermediate
3391efd51863SBarry Smith 
3392f6dfbefdSBarry Smith    Note:
3393f6dfbefdSBarry Smith    Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3394c0df2a02SJed Brown 
33951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`
3396efd51863SBarry Smith @*/
3397d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3398d71ae5a4SJacob Faibussowitsch {
3399efd51863SBarry Smith   PetscFunctionBegin;
3400efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3401efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3402efd51863SBarry Smith   snes->gridsequence = steps;
34033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3404efd51863SBarry Smith }
3405efd51863SBarry Smith 
3406fa19ca70SBarry Smith /*@
3407f6dfbefdSBarry Smith    SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3408fa19ca70SBarry Smith 
3409c3339decSBarry Smith    Logically Collective
3410fa19ca70SBarry Smith 
3411fa19ca70SBarry Smith    Input Parameter:
3412f6dfbefdSBarry Smith .  snes - the `SNES` context
3413fa19ca70SBarry Smith 
3414fa19ca70SBarry Smith    Output Parameter:
3415fa19ca70SBarry Smith .  steps - the number of refinements to do, defaults to 0
3416fa19ca70SBarry Smith 
3417f6dfbefdSBarry Smith    Options Database Key:
341867b8a455SSatish Balay .    -snes_grid_sequence <steps> - set number of refinements
3419fa19ca70SBarry Smith 
3420fa19ca70SBarry Smith    Level: intermediate
3421fa19ca70SBarry Smith 
3422f6dfbefdSBarry Smith    Note:
3423f6dfbefdSBarry Smith    Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3424fa19ca70SBarry Smith 
34251cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3426fa19ca70SBarry Smith @*/
3427d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3428d71ae5a4SJacob Faibussowitsch {
3429fa19ca70SBarry Smith   PetscFunctionBegin;
3430fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3431fa19ca70SBarry Smith   *steps = snes->gridsequence;
34323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3433fa19ca70SBarry Smith }
3434fa19ca70SBarry Smith 
3435a8054027SBarry Smith /*@
3436f6dfbefdSBarry Smith    SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3437a8054027SBarry Smith 
34383f9fe445SBarry Smith    Not Collective
3439a8054027SBarry Smith 
3440a8054027SBarry Smith    Input Parameter:
3441f6dfbefdSBarry Smith .  snes - the `SNES` context
3442a8054027SBarry Smith 
3443a8054027SBarry Smith    Output Parameter:
3444a8054027SBarry 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
34453b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3446a8054027SBarry Smith 
3447a8054027SBarry Smith    Options Database Keys:
344879a4f3cfSmarkadams4 +    -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves
34493d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
345079a4f3cfSmarkadams4 .    -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
34513d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3452a8054027SBarry Smith 
3453dc4c0fb0SBarry Smith    Level: intermediate
3454dc4c0fb0SBarry Smith 
3455a8054027SBarry Smith    Notes:
3456a8054027SBarry Smith    The default is 1
3457f6dfbefdSBarry Smith 
3458a8054027SBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3459a8054027SBarry Smith 
34601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3461a8054027SBarry Smith @*/
3462d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3463d71ae5a4SJacob Faibussowitsch {
3464a8054027SBarry Smith   PetscFunctionBegin;
34650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3466a8054027SBarry Smith   *lag = snes->lagpreconditioner;
34673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3468a8054027SBarry Smith }
3469a8054027SBarry Smith 
3470e35cf81dSBarry Smith /*@
3471f6dfbefdSBarry Smith    SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3472e35cf81dSBarry Smith      often the preconditioner is rebuilt.
3473e35cf81dSBarry Smith 
3474c3339decSBarry Smith    Logically Collective
3475e35cf81dSBarry Smith 
3476e35cf81dSBarry Smith    Input Parameters:
3477f6dfbefdSBarry Smith +  snes - the `SNES` context
3478e35cf81dSBarry 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
3479fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3480e35cf81dSBarry Smith 
3481e35cf81dSBarry Smith    Options Database Keys:
348279a4f3cfSmarkadams4 +    -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves
34833d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
348479a4f3cfSmarkadams4 .    -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
34853d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag.
3486e35cf81dSBarry Smith 
3487dc4c0fb0SBarry Smith    Level: intermediate
3488dc4c0fb0SBarry Smith 
3489e35cf81dSBarry Smith    Notes:
3490e35cf81dSBarry Smith    The default is 1
3491f6dfbefdSBarry Smith 
3492e35cf81dSBarry Smith    The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3493f6dfbefdSBarry Smith 
3494fe3ffe1eSBarry 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
3495fe3ffe1eSBarry Smith    at the next Newton step but never again (unless it is reset to another value)
3496e35cf81dSBarry Smith 
34971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3498e35cf81dSBarry Smith @*/
3499d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3500d71ae5a4SJacob Faibussowitsch {
3501e35cf81dSBarry Smith   PetscFunctionBegin;
35020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35035f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35045f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3505c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3506e35cf81dSBarry Smith   snes->lagjacobian = lag;
35073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3508e35cf81dSBarry Smith }
3509e35cf81dSBarry Smith 
3510e35cf81dSBarry Smith /*@
3511f6dfbefdSBarry Smith    SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3512e35cf81dSBarry Smith 
35133f9fe445SBarry Smith    Not Collective
3514e35cf81dSBarry Smith 
3515e35cf81dSBarry Smith    Input Parameter:
3516f6dfbefdSBarry Smith .  snes - the `SNES` context
3517e35cf81dSBarry Smith 
3518e35cf81dSBarry Smith    Output Parameter:
3519e35cf81dSBarry 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
3520e35cf81dSBarry Smith          the Jacobian is built etc.
3521e35cf81dSBarry Smith 
3522dc4c0fb0SBarry Smith    Level: intermediate
3523dc4c0fb0SBarry Smith 
3524e35cf81dSBarry Smith    Notes:
3525e35cf81dSBarry Smith    The default is 1
3526f6dfbefdSBarry Smith 
3527f6dfbefdSBarry Smith    The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3528e35cf81dSBarry Smith 
35291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3530e35cf81dSBarry Smith 
3531e35cf81dSBarry Smith @*/
3532d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3533d71ae5a4SJacob Faibussowitsch {
3534e35cf81dSBarry Smith   PetscFunctionBegin;
35350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3536e35cf81dSBarry Smith   *lag = snes->lagjacobian;
35373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3538e35cf81dSBarry Smith }
3539e35cf81dSBarry Smith 
354037ec4e1aSPeter Brune /*@
3541f6dfbefdSBarry Smith    SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
354237ec4e1aSPeter Brune 
3543c3339decSBarry Smith    Logically collective
354437ec4e1aSPeter Brune 
3545d8d19677SJose E. Roman    Input Parameters:
3546f6dfbefdSBarry Smith +  snes - the `SNES` context
35479d7e2deaSPeter Brune -   flg - jacobian lagging persists if true
354837ec4e1aSPeter Brune 
354937ec4e1aSPeter Brune    Options Database Keys:
355079a4f3cfSmarkadams4 +    -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves
35513d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
355279a4f3cfSmarkadams4 .    -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35533d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
35543d5a8a6aSBarry Smith 
3555dc4c0fb0SBarry Smith    Level: advanced
3556dc4c0fb0SBarry Smith 
355795452b02SPatrick Sanan    Notes:
3558f6dfbefdSBarry Smith     Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3559f6dfbefdSBarry Smith 
356095452b02SPatrick Sanan     This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
356137ec4e1aSPeter Brune    several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
356237ec4e1aSPeter Brune    timesteps may present huge efficiency gains.
356337ec4e1aSPeter Brune 
35641cc06b55SBarry Smith .seealso: [](ch_snes), `SNES, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagJacobianPersists()`
356537ec4e1aSPeter Brune @*/
3566d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3567d71ae5a4SJacob Faibussowitsch {
356837ec4e1aSPeter Brune   PetscFunctionBegin;
356937ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
357037ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
357137ec4e1aSPeter Brune   snes->lagjac_persist = flg;
35723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
357337ec4e1aSPeter Brune }
357437ec4e1aSPeter Brune 
357537ec4e1aSPeter Brune /*@
3576d8e291bfSBarry Smith    SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
357737ec4e1aSPeter Brune 
3578c3339decSBarry Smith    Logically Collective
357937ec4e1aSPeter Brune 
3580d8d19677SJose E. Roman    Input Parameters:
3581f6dfbefdSBarry Smith +  snes - the `SNES` context
35829d7e2deaSPeter Brune -   flg - preconditioner lagging persists if true
358337ec4e1aSPeter Brune 
358437ec4e1aSPeter Brune    Options Database Keys:
358579a4f3cfSmarkadams4 +    -snes_lag_jacobian_persists <true,false> - sets the persistence through multiple SNES solves
35863d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
358779a4f3cfSmarkadams4 .    -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35883d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
358937ec4e1aSPeter Brune 
3590dc4c0fb0SBarry Smith    Level: developer
3591dc4c0fb0SBarry Smith 
359295452b02SPatrick Sanan    Notes:
3593f6dfbefdSBarry Smith     Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3594f6dfbefdSBarry Smith 
359595452b02SPatrick Sanan    This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
359637ec4e1aSPeter Brune    by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
359737ec4e1aSPeter Brune    several timesteps may present huge efficiency gains.
359837ec4e1aSPeter Brune 
35991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
360037ec4e1aSPeter Brune @*/
3601d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3602d71ae5a4SJacob Faibussowitsch {
360337ec4e1aSPeter Brune   PetscFunctionBegin;
360437ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
360537ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
360637ec4e1aSPeter Brune   snes->lagpre_persist = flg;
36073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
360837ec4e1aSPeter Brune }
360937ec4e1aSPeter Brune 
36109b94acceSBarry Smith /*@
3611f6dfbefdSBarry Smith    SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3612be5caee7SBarry Smith 
3613c3339decSBarry Smith    Logically Collective
3614be5caee7SBarry Smith 
3615be5caee7SBarry Smith    Input Parameters:
3616f6dfbefdSBarry Smith +  snes - the `SNES` context
3617f6dfbefdSBarry Smith -  force - `PETSC_TRUE` require at least one iteration
3618be5caee7SBarry Smith 
3619f6dfbefdSBarry Smith    Options Database Key:
3620be5caee7SBarry Smith .    -snes_force_iteration <force> - Sets forcing an iteration
3621be5caee7SBarry Smith 
3622dc4c0fb0SBarry Smith    Level: intermediate
3623dc4c0fb0SBarry Smith 
3624f6dfbefdSBarry Smith    Note:
3625f6dfbefdSBarry Smith    This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3626be5caee7SBarry Smith 
36271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3628be5caee7SBarry Smith @*/
3629d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3630d71ae5a4SJacob Faibussowitsch {
3631be5caee7SBarry Smith   PetscFunctionBegin;
3632be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3633be5caee7SBarry Smith   snes->forceiteration = force;
36343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3635be5caee7SBarry Smith }
3636be5caee7SBarry Smith 
363785216dc7SFande Kong /*@
3638f6dfbefdSBarry Smith    SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
363985216dc7SFande Kong 
3640c3339decSBarry Smith    Logically Collective
364185216dc7SFande Kong 
36422fe279fdSBarry Smith    Input Parameter:
3643f6dfbefdSBarry Smith .  snes - the `SNES` context
364485216dc7SFande Kong 
364585216dc7SFande Kong    Output Parameter:
3646dc4c0fb0SBarry Smith .  force - `PETSC_TRUE` requires at least one iteration.
364785216dc7SFande Kong 
364806dd6b0eSSatish Balay    Level: intermediate
364906dd6b0eSSatish Balay 
36501cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
365185216dc7SFande Kong @*/
3652d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3653d71ae5a4SJacob Faibussowitsch {
365485216dc7SFande Kong   PetscFunctionBegin;
365585216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
365685216dc7SFande Kong   *force = snes->forceiteration;
36573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
365885216dc7SFande Kong }
3659be5caee7SBarry Smith 
3660be5caee7SBarry Smith /*@
3661f6dfbefdSBarry Smith    SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
36629b94acceSBarry Smith 
3663c3339decSBarry Smith    Logically Collective
3664c7afd0dbSLois Curfman McInnes 
36659b94acceSBarry Smith    Input Parameters:
3666f6dfbefdSBarry Smith +  snes - the `SNES` context
366770441072SBarry Smith .  abstol - absolute convergence tolerance
366833174efeSLois Curfman McInnes .  rtol - relative convergence tolerance
36695358d0d4SBarry Smith .  stol -  convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3670f6dfbefdSBarry Smith .  maxit - maximum number of iterations, default 50.
3671f6dfbefdSBarry Smith -  maxf - maximum number of function evaluations (-1 indicates no limit), default 1000
3672fee21e36SBarry Smith 
367333174efeSLois Curfman McInnes    Options Database Keys:
367470441072SBarry Smith +    -snes_atol <abstol> - Sets abstol
3675c7afd0dbSLois Curfman McInnes .    -snes_rtol <rtol> - Sets rtol
3676c7afd0dbSLois Curfman McInnes .    -snes_stol <stol> - Sets stol
3677c7afd0dbSLois Curfman McInnes .    -snes_max_it <maxit> - Sets maxit
3678c7afd0dbSLois Curfman McInnes -    -snes_max_funcs <maxf> - Sets maxf
36799b94acceSBarry Smith 
368036851e7fSLois Curfman McInnes    Level: intermediate
368136851e7fSLois Curfman McInnes 
36821cc06b55SBarry Smith .seealso: [](ch_snes), `SNESolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
36839b94acceSBarry Smith @*/
3684d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3685d71ae5a4SJacob Faibussowitsch {
36863a40ed3dSBarry Smith   PetscFunctionBegin;
36870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3688c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3689c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3690c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3691c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3692c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3693c5eb9154SBarry Smith 
369413bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
36955f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3696ab54825eSJed Brown     snes->abstol = abstol;
3697ab54825eSJed Brown   }
369813bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
36995f80ce2aSJacob 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);
3700ab54825eSJed Brown     snes->rtol = rtol;
3701ab54825eSJed Brown   }
370213bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
37035f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3704c60f73f4SPeter Brune     snes->stol = stol;
3705ab54825eSJed Brown   }
3706ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
370763a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3708ab54825eSJed Brown     snes->max_its = maxit;
3709ab54825eSJed Brown   }
3710ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
371163a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3712ab54825eSJed Brown     snes->max_funcs = maxf;
3713ab54825eSJed Brown   }
371488976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
37153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37169b94acceSBarry Smith }
37179b94acceSBarry Smith 
3718e4d06f11SPatrick Farrell /*@
3719f6dfbefdSBarry Smith    SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3720e4d06f11SPatrick Farrell 
3721c3339decSBarry Smith    Logically Collective
3722e4d06f11SPatrick Farrell 
3723e4d06f11SPatrick Farrell    Input Parameters:
3724f6dfbefdSBarry Smith +  snes - the `SNES` context
3725f6dfbefdSBarry Smith -  divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3726e4d06f11SPatrick Farrell 
3727f6dfbefdSBarry Smith    Options Database Key:
3728dc4c0fb0SBarry Smith .    -snes_divergence_tolerance <divtol> - Sets `divtol`
3729e4d06f11SPatrick Farrell 
3730e4d06f11SPatrick Farrell    Level: intermediate
3731e4d06f11SPatrick Farrell 
37321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3733e4d06f11SPatrick Farrell @*/
3734d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3735d71ae5a4SJacob Faibussowitsch {
3736e4d06f11SPatrick Farrell   PetscFunctionBegin;
3737e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3738e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3739e4d06f11SPatrick Farrell 
374013bcc0bdSJacob Faibussowitsch   if (divtol != (PetscReal)PETSC_DEFAULT) {
3741e4d06f11SPatrick Farrell     snes->divtol = divtol;
37429371c9d4SSatish Balay   } else {
3743e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3744e4d06f11SPatrick Farrell   }
37453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3746e4d06f11SPatrick Farrell }
3747e4d06f11SPatrick Farrell 
37489b94acceSBarry Smith /*@
374933174efeSLois Curfman McInnes    SNESGetTolerances - Gets various parameters used in convergence tests.
375033174efeSLois Curfman McInnes 
3751c7afd0dbSLois Curfman McInnes    Not Collective
3752c7afd0dbSLois Curfman McInnes 
375333174efeSLois Curfman McInnes    Input Parameters:
3754f6dfbefdSBarry Smith +  snes - the `SNES` context
375585385478SLisandro Dalcin .  atol - absolute convergence tolerance
375633174efeSLois Curfman McInnes .  rtol - relative convergence tolerance
375733174efeSLois Curfman McInnes .  stol -  convergence tolerance in terms of the norm
375833174efeSLois Curfman McInnes            of the change in the solution between steps
375933174efeSLois Curfman McInnes .  maxit - maximum number of iterations
3760c7afd0dbSLois Curfman McInnes -  maxf - maximum number of function evaluations
3761fee21e36SBarry Smith 
376236851e7fSLois Curfman McInnes    Level: intermediate
376336851e7fSLois Curfman McInnes 
3764dc4c0fb0SBarry Smith    Note:
3765dc4c0fb0SBarry Smith    The user can specify `NULL` for any parameter that is not needed.
3766dc4c0fb0SBarry Smith 
37671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
376833174efeSLois Curfman McInnes @*/
3769d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3770d71ae5a4SJacob Faibussowitsch {
37713a40ed3dSBarry Smith   PetscFunctionBegin;
37720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
377385385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
377433174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3775c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
377633174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
377733174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
37783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377933174efeSLois Curfman McInnes }
378033174efeSLois Curfman McInnes 
3781e4d06f11SPatrick Farrell /*@
3782e4d06f11SPatrick Farrell    SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3783e4d06f11SPatrick Farrell 
3784e4d06f11SPatrick Farrell    Not Collective
3785e4d06f11SPatrick Farrell 
3786e4d06f11SPatrick Farrell    Input Parameters:
3787f6dfbefdSBarry Smith +  snes - the `SNES` context
3788e4d06f11SPatrick Farrell -  divtol - divergence tolerance
3789e4d06f11SPatrick Farrell 
3790e4d06f11SPatrick Farrell    Level: intermediate
3791e4d06f11SPatrick Farrell 
37921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3793e4d06f11SPatrick Farrell @*/
3794d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3795d71ae5a4SJacob Faibussowitsch {
3796e4d06f11SPatrick Farrell   PetscFunctionBegin;
3797e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3798e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
37993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3800e4d06f11SPatrick Farrell }
3801e4d06f11SPatrick Farrell 
380233174efeSLois Curfman McInnes /*@
38039b94acceSBarry Smith    SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
38049b94acceSBarry Smith 
3805c3339decSBarry Smith    Logically Collective
3806fee21e36SBarry Smith 
3807c7afd0dbSLois Curfman McInnes    Input Parameters:
3808f6dfbefdSBarry Smith +  snes - the `SNES` context
3809c7afd0dbSLois Curfman McInnes -  tol - tolerance
3810c7afd0dbSLois Curfman McInnes 
38119b94acceSBarry Smith    Options Database Key:
38124a221d59SStefano Zampini .  -snes_tr_tol <tol> - Sets tol
38139b94acceSBarry Smith 
381436851e7fSLois Curfman McInnes    Level: intermediate
381536851e7fSLois Curfman McInnes 
38161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
38179b94acceSBarry Smith @*/
3818d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3819d71ae5a4SJacob Faibussowitsch {
38203a40ed3dSBarry Smith   PetscFunctionBegin;
38210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3822c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
38239b94acceSBarry Smith   snes->deltatol = tol;
38243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38259b94acceSBarry Smith }
38269b94acceSBarry Smith 
38276ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
38286ba87a44SLisandro Dalcin 
3829d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3830d71ae5a4SJacob Faibussowitsch {
3831b271bb04SBarry Smith   PetscDrawLG      lg;
3832b271bb04SBarry Smith   PetscReal        x, y, per;
3833b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3834b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3835b271bb04SBarry Smith   PetscDraw        draw;
3836b271bb04SBarry Smith 
3837459f5d12SBarry Smith   PetscFunctionBegin;
38384d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
38399566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
38409566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38419566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38429566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3843b271bb04SBarry Smith   x = (PetscReal)n;
384477b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
384594c9c6d3SKarl Rupp   else y = -15.0;
38469566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38476934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38489566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38499566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3850b271bb04SBarry Smith   }
3851b271bb04SBarry Smith 
38529566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
38539566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38549566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
3855aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
38569566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3857b271bb04SBarry Smith   x = (PetscReal)n;
3858b271bb04SBarry Smith   y = 100.0 * per;
38599566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38606934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38619566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38629566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3863b271bb04SBarry Smith   }
3864b271bb04SBarry Smith 
38659566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
38669371c9d4SSatish Balay   if (!n) {
38679371c9d4SSatish Balay     prev = rnorm;
38689371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
38699371c9d4SSatish Balay   }
38709566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38719566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3872b271bb04SBarry Smith   x = (PetscReal)n;
3873b271bb04SBarry Smith   y = (prev - rnorm) / prev;
38749566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38756934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38769566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38779566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3878b271bb04SBarry Smith   }
3879b271bb04SBarry Smith 
38809566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
38819566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38829566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38839566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3884b271bb04SBarry Smith   x = (PetscReal)n;
3885b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3886b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
38879566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3888b271bb04SBarry Smith   }
38896934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38909566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38919566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3892b271bb04SBarry Smith   }
3893b271bb04SBarry Smith   prev = rnorm;
38943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3895b271bb04SBarry Smith }
3896b271bb04SBarry Smith 
3897228d79bcSJed Brown /*@
3898228d79bcSJed Brown    SNESMonitor - runs the user provided monitor routines, if they exist
3899228d79bcSJed Brown 
3900c3339decSBarry Smith    Collective
3901228d79bcSJed Brown 
3902228d79bcSJed Brown    Input Parameters:
3903f6dfbefdSBarry Smith +  snes - nonlinear solver context obtained from `SNESCreate()`
3904228d79bcSJed Brown .  iter - iteration number
3905228d79bcSJed Brown -  rnorm - relative norm of the residual
3906228d79bcSJed Brown 
3907dc4c0fb0SBarry Smith    Level: developer
3908dc4c0fb0SBarry Smith 
3909f6dfbefdSBarry Smith    Note:
3910f6dfbefdSBarry Smith    This routine is called by the `SNES` implementations.
3911228d79bcSJed Brown    It does not typically need to be called by the user.
3912228d79bcSJed Brown 
39131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
3914228d79bcSJed Brown @*/
3915d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
3916d71ae5a4SJacob Faibussowitsch {
39177a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
39187a03ce2fSLisandro Dalcin 
39197a03ce2fSLisandro Dalcin   PetscFunctionBegin;
39209566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
392148a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
39229566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
39233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39247a03ce2fSLisandro Dalcin }
39257a03ce2fSLisandro Dalcin 
39269b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
39279b94acceSBarry Smith 
3928bf388a1fSBarry Smith /*MC
3929f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
3930bf388a1fSBarry Smith 
3931bf388a1fSBarry Smith      Synopsis:
3932aaa7dc30SBarry Smith      #include <petscsnes.h>
393337fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
3934bf388a1fSBarry Smith 
3935c3339decSBarry Smith      Collective
39361843f636SBarry Smith 
39371843f636SBarry Smith     Input Parameters:
3938f6dfbefdSBarry Smith +    snes - the `SNES` context
3939bf388a1fSBarry Smith .    its - iteration number
3940bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
3941bf388a1fSBarry Smith -    mctx - [optional] monitoring context
3942bf388a1fSBarry Smith 
3943878cb397SSatish Balay    Level: advanced
3944878cb397SSatish Balay 
39451cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
3946bf388a1fSBarry Smith M*/
3947bf388a1fSBarry Smith 
39489b94acceSBarry Smith /*@C
3949a6570f20SBarry Smith    SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
39509b94acceSBarry Smith    iteration of the nonlinear solver to display the iteration's
39519b94acceSBarry Smith    progress.
39529b94acceSBarry Smith 
3953c3339decSBarry Smith    Logically Collective
3954fee21e36SBarry Smith 
3955c7afd0dbSLois Curfman McInnes    Input Parameters:
3956f6dfbefdSBarry Smith +  snes - the `SNES` context
395720f4b53cSBarry Smith .  f - the monitor function,  for the calling sequence see `SNESMonitorFunction`
3958b8a78c4aSBarry Smith .  mctx - [optional] user-defined context for private data for the
3959dc4c0fb0SBarry Smith           monitor routine (use `NULL` if no context is desired)
3960dc4c0fb0SBarry Smith -  monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
39619b94acceSBarry Smith 
39629665c990SLois Curfman McInnes    Options Database Keys:
3963f6dfbefdSBarry Smith +    -snes_monitor        - sets `SNESMonitorDefault()`
3964798534f6SMatthew G. Knepley .    -snes_monitor draw::draw_lg - sets line graph monitor,
3965dc4c0fb0SBarry 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
3966c7afd0dbSLois Curfman McInnes                             the options database.
39679665c990SLois Curfman McInnes 
3968dc4c0fb0SBarry Smith    Level: intermediate
3969dc4c0fb0SBarry Smith 
3970f6dfbefdSBarry Smith    Note:
39716bc08f3fSLois Curfman McInnes    Several different monitoring routines may be set by calling
3972f6dfbefdSBarry Smith    `SNESMonitorSet()` multiple times; all will be called in the
39736bc08f3fSLois Curfman McInnes    order in which they were set.
3974639f9d9dSBarry Smith 
3975f6dfbefdSBarry Smith    Fortran Note:
3976f6dfbefdSBarry Smith    Only a single monitor function can be set for each `SNES` object
3977025f1a04SBarry Smith 
39781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
39799b94acceSBarry Smith @*/
3980d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
3981d71ae5a4SJacob Faibussowitsch {
3982b90d0a6eSBarry Smith   PetscInt  i;
398378064530SBarry Smith   PetscBool identical;
3984b90d0a6eSBarry Smith 
39853a40ed3dSBarry Smith   PetscFunctionBegin;
39860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3987b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
39889566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
39893ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
3990649052a6SBarry Smith   }
39915f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
39926e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
3993b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
3994639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
39953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39969b94acceSBarry Smith }
39979b94acceSBarry Smith 
3998a278d85bSSatish Balay /*@
3999f6dfbefdSBarry Smith    SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
40005cd90555SBarry Smith 
4001c3339decSBarry Smith    Logically Collective
4002c7afd0dbSLois Curfman McInnes 
40032fe279fdSBarry Smith    Input Parameter:
4004f6dfbefdSBarry Smith .  snes - the `SNES` context
40055cd90555SBarry Smith 
40061a480d89SAdministrator    Options Database Key:
4007a6570f20SBarry Smith .  -snes_monitor_cancel - cancels all monitors that have been hardwired
4008dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4009c7afd0dbSLois Curfman McInnes     set via the options database
40105cd90555SBarry Smith 
4011dc4c0fb0SBarry Smith    Level: intermediate
4012dc4c0fb0SBarry Smith 
4013f6dfbefdSBarry Smith    Note:
4014f6dfbefdSBarry Smith    There is no way to clear one specific monitor from a `SNES` object.
40155cd90555SBarry Smith 
40161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
40175cd90555SBarry Smith @*/
4018d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4019d71ae5a4SJacob Faibussowitsch {
4020d952e501SBarry Smith   PetscInt i;
4021d952e501SBarry Smith 
40225cd90555SBarry Smith   PetscFunctionBegin;
40230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4024d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
402548a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4026d952e501SBarry Smith   }
40275cd90555SBarry Smith   snes->numbermonitors = 0;
40283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40295cd90555SBarry Smith }
40305cd90555SBarry Smith 
4031bf388a1fSBarry Smith /*MC
4032bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4033bf388a1fSBarry Smith 
4034bf388a1fSBarry Smith      Synopsis:
4035aaa7dc30SBarry Smith      #include <petscsnes.h>
403637fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4037bf388a1fSBarry Smith 
4038c3339decSBarry Smith      Collective
40391843f636SBarry Smith 
40401843f636SBarry Smith     Input Parameters:
4041f6dfbefdSBarry Smith +    snes - the `SNES` context
4042bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4043bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4044bf388a1fSBarry Smith .    gnorm - 2-norm of current step
40451843f636SBarry Smith .    f - 2-norm of function
40461843f636SBarry Smith -    cctx - [optional] convergence context
40471843f636SBarry Smith 
40481843f636SBarry Smith     Output Parameter:
40491843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4050bf388a1fSBarry Smith 
4051878cb397SSatish Balay    Level: intermediate
4052bf388a1fSBarry Smith 
40531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4054bf388a1fSBarry Smith M*/
4055bf388a1fSBarry Smith 
40569b94acceSBarry Smith /*@C
40579b94acceSBarry Smith    SNESSetConvergenceTest - Sets the function that is to be used
40589b94acceSBarry Smith    to test for convergence of the nonlinear iterative solution.
40599b94acceSBarry Smith 
4060c3339decSBarry Smith    Logically Collective
4061fee21e36SBarry Smith 
4062c7afd0dbSLois Curfman McInnes    Input Parameters:
4063f6dfbefdSBarry Smith +  snes - the `SNES` context
4064f6dfbefdSBarry Smith .  `SNESConvergenceTestFunction` - routine to test for convergence
4065dc4c0fb0SBarry Smith .  cctx - [optional] context for private data for the convergence routine  (may be `NULL`)
4066dc4c0fb0SBarry Smith -  destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
40679b94acceSBarry Smith 
406836851e7fSLois Curfman McInnes    Level: advanced
406936851e7fSLois Curfman McInnes 
40701cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
40719b94acceSBarry Smith @*/
4072d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4073d71ae5a4SJacob Faibussowitsch {
40743a40ed3dSBarry Smith   PetscFunctionBegin;
40750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4076e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
40771baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4078bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
40797f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
408085385478SLisandro Dalcin   snes->cnvP                  = cctx;
40813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40829b94acceSBarry Smith }
40839b94acceSBarry Smith 
408452baeb72SSatish Balay /*@
4085f6dfbefdSBarry Smith    SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4086184914b5SBarry Smith 
4087184914b5SBarry Smith    Not Collective
4088184914b5SBarry Smith 
4089184914b5SBarry Smith    Input Parameter:
4090f6dfbefdSBarry Smith .  snes - the `SNES` context
4091184914b5SBarry Smith 
4092184914b5SBarry Smith    Output Parameter:
4093f6dfbefdSBarry Smith .  reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4094184914b5SBarry Smith 
4095f6dfbefdSBarry Smith    Options Database Key:
40966a4d7782SBarry Smith .   -snes_converged_reason - prints the reason to standard out
40976a4d7782SBarry Smith 
4098184914b5SBarry Smith    Level: intermediate
4099184914b5SBarry Smith 
4100f6dfbefdSBarry Smith    Note:
4101f6dfbefdSBarry Smith     Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4102184914b5SBarry Smith 
41031cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4104184914b5SBarry Smith @*/
4105d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4106d71ae5a4SJacob Faibussowitsch {
4107184914b5SBarry Smith   PetscFunctionBegin;
41080700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41094482741eSBarry Smith   PetscValidPointer(reason, 2);
4110184914b5SBarry Smith   *reason = snes->reason;
41113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4112184914b5SBarry Smith }
4113184914b5SBarry Smith 
4114c4421ceaSFande Kong /*@C
4115f6dfbefdSBarry Smith    SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4116c4421ceaSFande Kong 
4117c4421ceaSFande Kong    Not Collective
4118c4421ceaSFande Kong 
4119c4421ceaSFande Kong    Input Parameter:
4120f6dfbefdSBarry Smith .  snes - the `SNES` context
4121c4421ceaSFande Kong 
4122c4421ceaSFande Kong    Output Parameter:
4123dc4c0fb0SBarry Smith .  strreason - a human readable string that describes `SNES` converged reason
4124c4421ceaSFande Kong 
412599c90e12SSatish Balay    Level: beginner
4126c4421ceaSFande Kong 
41271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4128c4421ceaSFande Kong @*/
4129d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4130d71ae5a4SJacob Faibussowitsch {
4131c4421ceaSFande Kong   PetscFunctionBegin;
4132c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4133dadcf809SJacob Faibussowitsch   PetscValidPointer(strreason, 2);
4134c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
41353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4136c4421ceaSFande Kong }
4137c4421ceaSFande Kong 
413833866048SMatthew G. Knepley /*@
4139f6dfbefdSBarry Smith    SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
414033866048SMatthew G. Knepley 
414133866048SMatthew G. Knepley    Not Collective
414233866048SMatthew G. Knepley 
414333866048SMatthew G. Knepley    Input Parameters:
4144f6dfbefdSBarry Smith +  snes - the `SNES` context
4145f6dfbefdSBarry Smith -  reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
414633866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
414733866048SMatthew G. Knepley 
4148f6dfbefdSBarry Smith    Level: developer
4149f6dfbefdSBarry Smith 
4150f6dfbefdSBarry Smith    Developer Note:
4151f6dfbefdSBarry Smith    Called inside the various `SNESSolve()` implementations
415233866048SMatthew G. Knepley 
41531cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
415433866048SMatthew G. Knepley @*/
4155d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4156d71ae5a4SJacob Faibussowitsch {
415733866048SMatthew G. Knepley   PetscFunctionBegin;
415833866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
415933866048SMatthew G. Knepley   snes->reason = reason;
41603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
416133866048SMatthew G. Knepley }
416233866048SMatthew G. Knepley 
4163c9005455SLois Curfman McInnes /*@
4164c9005455SLois Curfman McInnes    SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
4165c9005455SLois Curfman McInnes 
4166c3339decSBarry Smith    Logically Collective
4167fee21e36SBarry Smith 
4168c7afd0dbSLois Curfman McInnes    Input Parameters:
4169f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
41708c7482ecSBarry Smith .  a   - array to hold history, this array will contain the function norms computed at each step
4171cd5578b5SBarry Smith .  its - integer array holds the number of linear iterations for each solve.
4172758f92a0SBarry Smith .  na  - size of a and its
4173f6dfbefdSBarry Smith -  reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4174758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4175c7afd0dbSLois Curfman McInnes 
4176dc4c0fb0SBarry Smith    Level: intermediate
4177dc4c0fb0SBarry Smith 
4178308dcc3eSBarry Smith    Notes:
4179dc4c0fb0SBarry Smith    If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4180308dcc3eSBarry Smith    default array of length 10000 is allocated.
4181308dcc3eSBarry Smith 
4182c9005455SLois Curfman McInnes    This routine is useful, e.g., when running a code for purposes
4183c9005455SLois Curfman McInnes    of accurate performance monitoring, when no I/O should be done
4184c9005455SLois Curfman McInnes    during the section of code that is being timed.
4185c9005455SLois Curfman McInnes 
41861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4187c9005455SLois Curfman McInnes @*/
4188d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4189d71ae5a4SJacob Faibussowitsch {
41903a40ed3dSBarry Smith   PetscFunctionBegin;
41910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4192064a246eSJacob Faibussowitsch   if (a) PetscValidRealPointer(a, 2);
4193a562a398SLisandro Dalcin   if (its) PetscValidIntPointer(its, 3);
41947a1ec6d4SBarry Smith   if (!a) {
4195308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
41969566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4197071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4198308dcc3eSBarry Smith   }
4199c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4200758f92a0SBarry Smith   snes->conv_hist_its   = its;
4201115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4202a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4203758f92a0SBarry Smith   snes->conv_hist_reset = reset;
42043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4205758f92a0SBarry Smith }
4206758f92a0SBarry Smith 
4207d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4208c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4209c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
421099e0435eSBarry Smith 
4211d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4212d71ae5a4SJacob Faibussowitsch {
4213308dcc3eSBarry Smith   mxArray   *mat;
4214308dcc3eSBarry Smith   PetscInt   i;
4215308dcc3eSBarry Smith   PetscReal *ar;
4216308dcc3eSBarry Smith 
4217308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4218308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4219f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
422011cc89d2SBarry Smith   return mat;
4221308dcc3eSBarry Smith }
4222308dcc3eSBarry Smith #endif
4223308dcc3eSBarry Smith 
42240c4c9dddSBarry Smith /*@C
4225758f92a0SBarry Smith    SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
4226758f92a0SBarry Smith 
42273f9fe445SBarry Smith    Not Collective
4228758f92a0SBarry Smith 
4229758f92a0SBarry Smith    Input Parameter:
4230f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
4231758f92a0SBarry Smith 
4232758f92a0SBarry Smith    Output Parameters:
4233f6dfbefdSBarry Smith +  a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4234758f92a0SBarry Smith .  its - integer array holds the number of linear iterations (or
4235758f92a0SBarry Smith          negative if not converged) for each solve.
423620f4b53cSBarry Smith -  na  - size of `a` and `its`
4237758f92a0SBarry Smith 
4238dc4c0fb0SBarry Smith    Level: intermediate
4239dc4c0fb0SBarry Smith 
424020f4b53cSBarry Smith    Note:
424120f4b53cSBarry Smith    This routine is useful, e.g., when running a code for purposes
424220f4b53cSBarry Smith    of accurate performance monitoring, when no I/O should be done
424320f4b53cSBarry Smith    during the section of code that is being timed.
424420f4b53cSBarry Smith 
424520f4b53cSBarry Smith    Fortran Note:
4246758f92a0SBarry Smith     The calling sequence for this routine in Fortran is
4247dc4c0fb0SBarry Smith .vb
4248dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4249dc4c0fb0SBarry Smith .ve
4250758f92a0SBarry Smith 
42511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4252758f92a0SBarry Smith @*/
4253d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4254d71ae5a4SJacob Faibussowitsch {
4255758f92a0SBarry Smith   PetscFunctionBegin;
42560700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4257758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4258758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4259115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
42603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4261c9005455SLois Curfman McInnes }
4262c9005455SLois Curfman McInnes 
4263ac226902SBarry Smith /*@C
426476b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4265eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
42667e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
426776b2cf59SMatthew Knepley 
4268c3339decSBarry Smith   Logically Collective
426976b2cf59SMatthew Knepley 
427076b2cf59SMatthew Knepley   Input Parameters:
4271a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4272a2b725a8SWilliam Gropp - func - The function
427376b2cf59SMatthew Knepley 
427420f4b53cSBarry Smith   Calling sequence of `func`:
427520f4b53cSBarry Smith $ PetscErrorCode func(SNES snes, PetscInt step);
427620f4b53cSBarry Smith + snes - the nonlinear solver context
427720f4b53cSBarry Smith - step - The current step of the iteration
427876b2cf59SMatthew Knepley 
4279fe97e370SBarry Smith   Level: advanced
4280fe97e370SBarry Smith 
42816b7fb656SBarry Smith   Note:
4282f6dfbefdSBarry 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
4283f6dfbefdSBarry Smith      to `SNESSetFunction()`, or `SNESSetPicard()`
4284fe97e370SBarry Smith      This is not used by most users.
428576b2cf59SMatthew Knepley 
4286aaa8cc7dSPierre 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.
42876b7fb656SBarry Smith 
42881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESSolve()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4289db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
429076b2cf59SMatthew Knepley @*/
4291d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
4292d71ae5a4SJacob Faibussowitsch {
429376b2cf59SMatthew Knepley   PetscFunctionBegin;
42940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4295e7788613SBarry Smith   snes->ops->update = func;
42963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
429776b2cf59SMatthew Knepley }
429876b2cf59SMatthew Knepley 
42999b94acceSBarry Smith /*
43009b94acceSBarry Smith    SNESScaleStep_Private - Scales a step so that its length is less than the
43019b94acceSBarry Smith    positive parameter delta.
43029b94acceSBarry Smith 
43039b94acceSBarry Smith     Input Parameters:
4304f6dfbefdSBarry Smith +   snes - the `SNES` context
43059b94acceSBarry Smith .   y - approximate solution of linear system
43069b94acceSBarry Smith .   fnorm - 2-norm of current function
4307c7afd0dbSLois Curfman McInnes -   delta - trust region size
43089b94acceSBarry Smith 
43099b94acceSBarry Smith     Output Parameters:
4310c7afd0dbSLois Curfman McInnes +   gpnorm - predicted function norm at the new point, assuming local
43119b94acceSBarry Smith     linearization.  The value is zero if the step lies within the trust
43129b94acceSBarry Smith     region, and exceeds zero otherwise.
4313c7afd0dbSLois Curfman McInnes -   ynorm - 2-norm of the step
43149b94acceSBarry Smith 
4315f6dfbefdSBarry Smith     Level: developer
43169b94acceSBarry Smith 
4317f6dfbefdSBarry Smith     Note:
4318f6dfbefdSBarry Smith     For non-trust region methods such as `SNESNEWTONLS`, the parameter delta
4319f6dfbefdSBarry Smith     is set to be the maximum allowable step size.
43209b94acceSBarry Smith */
4321d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESScaleStep_Private(SNES snes, Vec y, PetscReal *fnorm, PetscReal *delta, PetscReal *gpnorm, PetscReal *ynorm)
4322d71ae5a4SJacob Faibussowitsch {
4323064f8208SBarry Smith   PetscReal   nrm;
4324ea709b57SSatish Balay   PetscScalar cnorm;
43253a40ed3dSBarry Smith 
43263a40ed3dSBarry Smith   PetscFunctionBegin;
43270700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43280700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 2);
4329c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 2);
4330184914b5SBarry Smith 
43319566063dSJacob Faibussowitsch   PetscCall(VecNorm(y, NORM_2, &nrm));
4332064f8208SBarry Smith   if (nrm > *delta) {
4333064f8208SBarry Smith     nrm     = *delta / nrm;
4334064f8208SBarry Smith     *gpnorm = (1.0 - nrm) * (*fnorm);
4335064f8208SBarry Smith     cnorm   = nrm;
43369566063dSJacob Faibussowitsch     PetscCall(VecScale(y, cnorm));
43379b94acceSBarry Smith     *ynorm = *delta;
43389b94acceSBarry Smith   } else {
43399b94acceSBarry Smith     *gpnorm = 0.0;
4340064f8208SBarry Smith     *ynorm  = nrm;
43419b94acceSBarry Smith   }
43423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43439b94acceSBarry Smith }
43449b94acceSBarry Smith 
434591f3e32bSBarry Smith /*@C
4346f6dfbefdSBarry Smith    SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
43472a359c20SBarry Smith 
4348c3339decSBarry Smith    Collective
43492a359c20SBarry Smith 
43502a359c20SBarry Smith    Parameter:
4351f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
43522a359c20SBarry Smith -  viewer - the viewer to display the reason
43532a359c20SBarry Smith 
43542a359c20SBarry Smith    Options Database Keys:
4355ee300463SSatish Balay +  -snes_converged_reason - print reason for converged or diverged, also prints number of iterations
4356ee300463SSatish Balay -  -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4357eafd5ff0SAlex Lindsay 
4358f6dfbefdSBarry Smith   Note:
4359f6dfbefdSBarry Smith      To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4360f6dfbefdSBarry Smith      use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
43612a359c20SBarry Smith 
43622a359c20SBarry Smith    Level: beginner
43632a359c20SBarry Smith 
43641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4365f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4366f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4367db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
43682a359c20SBarry Smith @*/
4369d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4370d71ae5a4SJacob Faibussowitsch {
437175cca76cSMatthew G. Knepley   PetscViewerFormat format;
43722a359c20SBarry Smith   PetscBool         isAscii;
43732a359c20SBarry Smith 
43742a359c20SBarry Smith   PetscFunctionBegin;
437519a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
43769566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
43772a359c20SBarry Smith   if (isAscii) {
43789566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
43799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
438075cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
438175cca76cSMatthew G. Knepley       DM       dm;
438275cca76cSMatthew G. Knepley       Vec      u;
438375cca76cSMatthew G. Knepley       PetscDS  prob;
438475cca76cSMatthew G. Knepley       PetscInt Nf, f;
438595cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
438695cbbfd3SMatthew G. Knepley       void    **exactCtx;
438775cca76cSMatthew G. Knepley       PetscReal error;
438875cca76cSMatthew G. Knepley 
43899566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
43909566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
43919566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
43929566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
43939566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
43949566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
43959566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
43969566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
43979566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
439863a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
439975cca76cSMatthew G. Knepley     }
4400eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
44012a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
440263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
44032a359c20SBarry Smith       } else {
440463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44052a359c20SBarry Smith       }
4406eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
44072a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
440863a3b9bcSJacob 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));
44092a359c20SBarry Smith       } else {
441063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44112a359c20SBarry Smith       }
44122a359c20SBarry Smith     }
44139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
44142a359c20SBarry Smith   }
44153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44162a359c20SBarry Smith }
44172a359c20SBarry Smith 
4418c4421ceaSFande Kong /*@C
4419c4421ceaSFande Kong    SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4420aaa8cc7dSPierre Jolivet     end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4421c4421ceaSFande Kong 
4422c3339decSBarry Smith    Logically Collective
4423c4421ceaSFande Kong 
4424c4421ceaSFande Kong    Input Parameters:
4425f6dfbefdSBarry Smith +  snes - the `SNES` context
4426c4421ceaSFande Kong .  f - the snes converged reason view function
4427c4421ceaSFande Kong .  vctx - [optional] user-defined context for private data for the
4428dc4c0fb0SBarry Smith           snes converged reason view routine (use `NULL` if no context is desired)
4429dc4c0fb0SBarry Smith -  reasonviewdestroy - [optional] routine that frees reasonview context (may be `NULL`)
4430c4421ceaSFande Kong 
4431c4421ceaSFande Kong    Options Database Keys:
4432f6dfbefdSBarry Smith +    -snes_converged_reason        - sets a default `SNESConvergedReasonView()`
4433c4421ceaSFande Kong -    -snes_converged_reason_view_cancel - cancels all converged reason viewers that have
4434c4421ceaSFande Kong                             been hardwired into a code by
4435f6dfbefdSBarry Smith                             calls to `SNESConvergedReasonViewSet()`, but
4436c4421ceaSFande Kong                             does not cancel those set via
4437c4421ceaSFande Kong                             the options database.
4438c4421ceaSFande Kong 
4439dc4c0fb0SBarry Smith    Level: intermediate
4440dc4c0fb0SBarry Smith 
4441f6dfbefdSBarry Smith    Note:
4442c4421ceaSFande Kong    Several different converged reason view routines may be set by calling
4443f6dfbefdSBarry Smith    `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4444c4421ceaSFande Kong    order in which they were set.
4445c4421ceaSFande Kong 
44461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4447c4421ceaSFande Kong @*/
4448d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES, void *), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **))
4449d71ae5a4SJacob Faibussowitsch {
4450c4421ceaSFande Kong   PetscInt  i;
4451c4421ceaSFande Kong   PetscBool identical;
4452c4421ceaSFande Kong 
4453c4421ceaSFande Kong   PetscFunctionBegin;
4454c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4455c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
44569566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
44573ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4458c4421ceaSFande Kong   }
44595f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4460c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4461c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4462c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
44633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4464c4421ceaSFande Kong }
4465c4421ceaSFande Kong 
446691f3e32bSBarry Smith /*@
4467f6dfbefdSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed.
4468c4421ceaSFande Kong                                        All the user-provided convergedReasonView routines will be involved as well, if they exist.
44692a359c20SBarry Smith 
4470c3339decSBarry Smith   Collective
44712a359c20SBarry Smith 
44722fe279fdSBarry Smith   Input Parameter:
4473f6dfbefdSBarry Smith . snes   - the `SNES` object
44742a359c20SBarry Smith 
4475f6dfbefdSBarry Smith   Level: advanced
44762a359c20SBarry Smith 
44771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4478f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
44792a359c20SBarry Smith @*/
4480d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4481d71ae5a4SJacob Faibussowitsch {
44822a359c20SBarry Smith   PetscViewer       viewer;
44832a359c20SBarry Smith   PetscBool         flg;
44842a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
44852a359c20SBarry Smith   PetscViewerFormat format;
4486c4421ceaSFande Kong   PetscInt          i;
44872a359c20SBarry Smith 
44882a359c20SBarry Smith   PetscFunctionBegin;
44893ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
44902a359c20SBarry Smith   incall = PETSC_TRUE;
4491c4421ceaSFande Kong 
4492c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
449348a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4494c4421ceaSFande Kong 
4495c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
44969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
44972a359c20SBarry Smith   if (flg) {
44989566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
44999566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
45009566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
45019566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
45022a359c20SBarry Smith   }
45032a359c20SBarry Smith   incall = PETSC_FALSE;
45043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45052a359c20SBarry Smith }
45062a359c20SBarry Smith 
4507487a658cSBarry Smith /*@
4508f69a0ea3SMatthew Knepley    SNESSolve - Solves a nonlinear system F(x) = b.
4509f6dfbefdSBarry Smith    Call `SNESSolve()` after calling `SNESCreate()` and optional routines of the form `SNESSetXXX()`.
45109b94acceSBarry Smith 
4511c3339decSBarry Smith    Collective
4512c7afd0dbSLois Curfman McInnes 
4513b2002411SLois Curfman McInnes    Input Parameters:
4514f6dfbefdSBarry Smith +  snes - the `SNES` context
4515dc4c0fb0SBarry Smith .  b - the constant part of the equation F(x) = b, or `NULL` to use zero.
451685385478SLisandro Dalcin -  x - the solution vector.
45179b94acceSBarry Smith 
4518dc4c0fb0SBarry Smith    Level: beginner
4519dc4c0fb0SBarry Smith 
4520f6dfbefdSBarry Smith    Note:
45218ddd3da0SLois Curfman McInnes    The user should initialize the vector,x, with the initial guess
4522f6dfbefdSBarry Smith    for the nonlinear solve prior to calling `SNESSolve()`.  In particular,
45238ddd3da0SLois Curfman McInnes    to employ an initial guess of zero, the user should explicitly set
4524f6dfbefdSBarry Smith    this vector to zero by calling `VecSet()`.
45258ddd3da0SLois Curfman McInnes 
45261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4527db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4528db781477SPatrick Sanan           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
45299b94acceSBarry Smith @*/
4530d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4531d71ae5a4SJacob Faibussowitsch {
4532ace3abfcSBarry Smith   PetscBool flg;
4533efd51863SBarry Smith   PetscInt  grid;
45340298fd71SBarry Smith   Vec       xcreated = NULL;
4535caa4e7f2SJed Brown   DM        dm;
4536052efed2SBarry Smith 
45373a40ed3dSBarry Smith   PetscFunctionBegin;
45380700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4539a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4540a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
45410700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
454285385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
454385385478SLisandro Dalcin 
454434b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
454506fc46c8SMatthew G. Knepley   {
454606fc46c8SMatthew G. Knepley     PetscViewer       viewer;
454706fc46c8SMatthew G. Knepley     PetscViewerFormat format;
45487c88af5aSMatthew G. Knepley     PetscInt          num;
454906fc46c8SMatthew G. Knepley     PetscBool         flg;
455006fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
455106fc46c8SMatthew G. Knepley 
455206fc46c8SMatthew G. Knepley     if (!incall) {
455334b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
45549566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
455506fc46c8SMatthew G. Knepley       if (flg) {
455606fc46c8SMatthew G. Knepley         PetscConvEst conv;
455746079b62SMatthew G. Knepley         DM           dm;
455846079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
455946079b62SMatthew G. Knepley         PetscInt     Nf;
456006fc46c8SMatthew G. Knepley 
456106fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
45629566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
45639566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
45649566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
45659566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
45669566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
45679566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
45689566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
45699566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
45709566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
45719566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
45729566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
45739566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
45749566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
45759566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
457606fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
457706fc46c8SMatthew G. Knepley       }
457834b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4579b2588ea6SMatthew G. Knepley       num = 1;
45809566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
458134b4d3a8SMatthew G. Knepley       if (flg) {
458234b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
458334b4d3a8SMatthew G. Knepley 
458434b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
45859566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
45869566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
45879566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
45889566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
45899566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
45909566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
45919566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
459234b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
459334b4d3a8SMatthew G. Knepley       }
45947c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
45957c88af5aSMatthew G. Knepley       num = 0;
45969566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
45977c88af5aSMatthew G. Knepley       if (num) {
45987c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
45997c88af5aSMatthew G. Knepley 
46007c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
46019566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46029566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46039566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46049566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46069566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
46079566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
46087c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
46097c88af5aSMatthew G. Knepley       }
461006fc46c8SMatthew G. Knepley     }
461106fc46c8SMatthew G. Knepley   }
4612ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4613caa4e7f2SJed Brown   if (!x) {
46149566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
46159566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4616a69afd8bSBarry Smith     x = xcreated;
4617a69afd8bSBarry Smith   }
46189566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4619f05ece33SBarry Smith 
46209566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4621efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
462285385478SLisandro Dalcin     /* set solution vector */
46239566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
46249566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
462585385478SLisandro Dalcin     snes->vec_sol = x;
46269566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4627caa4e7f2SJed Brown 
4628caa4e7f2SJed Brown     /* set affine vector if provided */
46299566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
46309566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
463185385478SLisandro Dalcin     snes->vec_rhs = b;
463285385478SLisandro Dalcin 
46335f80ce2aSJacob 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");
46345f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
46355f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector");
4636aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
46379566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
46389566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
46393f149594SLisandro Dalcin 
46407eee914bSBarry Smith     if (!grid) {
464125e27a38SBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4642dd568438SSatish Balay     }
4643d25893d9SBarry Smith 
4644abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
46459371c9d4SSatish Balay     if (snes->counters_reset) {
46469371c9d4SSatish Balay       snes->nfuncs      = 0;
46479371c9d4SSatish Balay       snes->linear_its  = 0;
46489371c9d4SSatish Balay       snes->numFailures = 0;
46499371c9d4SSatish Balay     }
4650d5e45103SBarry Smith 
46519566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4652dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
46539566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
46545f80ce2aSJacob Faibussowitsch     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver returned without setting converged reason");
4655422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
46563f149594SLisandro Dalcin 
465737ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
465837ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
465937ec4e1aSPeter Brune 
46609566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
46619566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4662c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
46639566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
46645968eb51SBarry Smith 
46655f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
46669c8e83a9SBarry Smith     if (snes->reason < 0) break;
4667efd51863SBarry Smith     if (grid < snes->gridsequence) {
4668efd51863SBarry Smith       DM  fine;
4669efd51863SBarry Smith       Vec xnew;
4670efd51863SBarry Smith       Mat interp;
4671efd51863SBarry Smith 
46729566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
46735f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
46749566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
46759566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
46769566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
46779566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
46789566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4679efd51863SBarry Smith       x = xnew;
4680efd51863SBarry Smith 
46819566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
46829566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
46839566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
46849566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
46859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4686efd51863SBarry Smith     }
4687efd51863SBarry Smith   }
46889566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
46899566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
46909566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
46919566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
46923f7e2da0SPeter Brune 
46939566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
46949566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
46953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46969b94acceSBarry Smith }
46979b94acceSBarry Smith 
46989b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
46999b94acceSBarry Smith 
470082bf6240SBarry Smith /*@C
47014b0e389bSBarry Smith    SNESSetType - Sets the method for the nonlinear solver.
47029b94acceSBarry Smith 
4703c3339decSBarry Smith    Collective
4704fee21e36SBarry Smith 
4705c7afd0dbSLois Curfman McInnes    Input Parameters:
4706f6dfbefdSBarry Smith +  snes - the `SNES` context
4707454a90a3SBarry Smith -  type - a known method
4708c7afd0dbSLois Curfman McInnes 
4709c7afd0dbSLois Curfman McInnes    Options Database Key:
4710454a90a3SBarry Smith .  -snes_type <type> - Sets the method; use -help for a list
471104d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4712ae12b187SLois Curfman McInnes 
4713dc4c0fb0SBarry Smith   Level: intermediate
4714dc4c0fb0SBarry Smith 
47159b94acceSBarry Smith    Notes:
4716e090d566SSatish Balay    See "petsc/include/petscsnes.h" for available methods (for instance)
4717f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4718c7afd0dbSLois Curfman McInnes      (systems of nonlinear equations)
47194a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4720c7afd0dbSLois Curfman McInnes      (systems of nonlinear equations)
47219b94acceSBarry Smith 
4722f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4723f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4724ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4725ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4726f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4727ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4728ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4729ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4730ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4731b0a32e0cSBarry Smith   appropriate method.
473236851e7fSLois Curfman McInnes 
4733f6dfbefdSBarry Smith     Developer Note:
4734f6dfbefdSBarry Smith     `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4735f6dfbefdSBarry Smith     the constructor in that list and calls it to create the specific object.
47368f6c3df8SBarry Smith 
47371cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
47389b94acceSBarry Smith @*/
4739d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4740d71ae5a4SJacob Faibussowitsch {
4741ace3abfcSBarry Smith   PetscBool match;
47425f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
47433a40ed3dSBarry Smith 
47443a40ed3dSBarry Smith   PetscFunctionBegin;
47450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47464482741eSBarry Smith   PetscValidCharPointer(type, 2);
474782bf6240SBarry Smith 
47489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
47493ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
475092ff6ae8SBarry Smith 
47519566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
47525f80ce2aSJacob Faibussowitsch   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
475375396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4754dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
475575396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
47569e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
47579e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
47589e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
47599e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
47609e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
47617fe760d5SStefano Zampini 
47627fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
47639566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
47647fe760d5SStefano Zampini 
476575396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
476675396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4767f5af7f23SKarl Rupp 
47689566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
47699566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
47703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47719b94acceSBarry Smith }
47729b94acceSBarry Smith 
47739b94acceSBarry Smith /*@C
4774f6dfbefdSBarry Smith    SNESGetType - Gets the `SNES` method type and name (as a string).
47759b94acceSBarry Smith 
4776c7afd0dbSLois Curfman McInnes    Not Collective
4777c7afd0dbSLois Curfman McInnes 
47789b94acceSBarry Smith    Input Parameter:
47794b0e389bSBarry Smith .  snes - nonlinear solver context
47809b94acceSBarry Smith 
47819b94acceSBarry Smith    Output Parameter:
4782f6dfbefdSBarry Smith .  type - `SNES` method (a character string)
47839b94acceSBarry Smith 
478436851e7fSLois Curfman McInnes    Level: intermediate
478536851e7fSLois Curfman McInnes 
47861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
47879b94acceSBarry Smith @*/
4788d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4789d71ae5a4SJacob Faibussowitsch {
47903a40ed3dSBarry Smith   PetscFunctionBegin;
47910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47924482741eSBarry Smith   PetscValidPointer(type, 2);
47937adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
47943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47959b94acceSBarry Smith }
47969b94acceSBarry Smith 
47973cd8a7caSMatthew G. Knepley /*@
4798f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
47993cd8a7caSMatthew G. Knepley 
4800c3339decSBarry Smith   Logically Collective
48013cd8a7caSMatthew G. Knepley 
48023cd8a7caSMatthew G. Knepley   Input Parameters:
4803f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
48043cd8a7caSMatthew G. Knepley - u    - the solution vector
48053cd8a7caSMatthew G. Knepley 
48063cd8a7caSMatthew G. Knepley   Level: beginner
48073cd8a7caSMatthew G. Knepley 
48081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
48093cd8a7caSMatthew G. Knepley @*/
4810d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4811d71ae5a4SJacob Faibussowitsch {
48123cd8a7caSMatthew G. Knepley   DM dm;
48133cd8a7caSMatthew G. Knepley 
48143cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
48153cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48163cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
48179566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
48189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
48193cd8a7caSMatthew G. Knepley 
48203cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
48213cd8a7caSMatthew G. Knepley 
48229566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
48239566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
48243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48253cd8a7caSMatthew G. Knepley }
48263cd8a7caSMatthew G. Knepley 
482752baeb72SSatish Balay /*@
48289b94acceSBarry Smith    SNESGetSolution - Returns the vector where the approximate solution is
4829f6dfbefdSBarry Smith    stored. This is the fine grid solution when using `SNESSetGridSequence()`.
48309b94acceSBarry Smith 
4831f6dfbefdSBarry Smith    Not Collective, but x is parallel if snes is parallel
4832c7afd0dbSLois Curfman McInnes 
48339b94acceSBarry Smith    Input Parameter:
4834f6dfbefdSBarry Smith .  snes - the `SNES` context
48359b94acceSBarry Smith 
48369b94acceSBarry Smith    Output Parameter:
48379b94acceSBarry Smith .  x - the solution
48389b94acceSBarry Smith 
483970e92668SMatthew Knepley    Level: intermediate
484036851e7fSLois Curfman McInnes 
48411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
48429b94acceSBarry Smith @*/
4843d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4844d71ae5a4SJacob Faibussowitsch {
48453a40ed3dSBarry Smith   PetscFunctionBegin;
48460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48474482741eSBarry Smith   PetscValidPointer(x, 2);
484885385478SLisandro Dalcin   *x = snes->vec_sol;
48493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
485070e92668SMatthew Knepley }
485170e92668SMatthew Knepley 
485252baeb72SSatish Balay /*@
48539b94acceSBarry Smith    SNESGetSolutionUpdate - Returns the vector where the solution update is
48549b94acceSBarry Smith    stored.
48559b94acceSBarry Smith 
4856f6dfbefdSBarry Smith    Not Collective, but x is parallel if snes is parallel
4857c7afd0dbSLois Curfman McInnes 
48589b94acceSBarry Smith    Input Parameter:
4859f6dfbefdSBarry Smith .  snes - the `SNES` context
48609b94acceSBarry Smith 
48619b94acceSBarry Smith    Output Parameter:
48629b94acceSBarry Smith .  x - the solution update
48639b94acceSBarry Smith 
486436851e7fSLois Curfman McInnes    Level: advanced
486536851e7fSLois Curfman McInnes 
48661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
48679b94acceSBarry Smith @*/
4868d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4869d71ae5a4SJacob Faibussowitsch {
48703a40ed3dSBarry Smith   PetscFunctionBegin;
48710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48724482741eSBarry Smith   PetscValidPointer(x, 2);
487385385478SLisandro Dalcin   *x = snes->vec_sol_update;
48743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48759b94acceSBarry Smith }
48769b94acceSBarry Smith 
48779b94acceSBarry Smith /*@C
4878f6dfbefdSBarry Smith    SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
48799b94acceSBarry Smith 
4880f6dfbefdSBarry Smith    Not Collective, but r is parallel if snes is parallel. Collective if r is requested, but has not been created yet.
4881c7afd0dbSLois Curfman McInnes 
48829b94acceSBarry Smith    Input Parameter:
4883f6dfbefdSBarry Smith .  snes - the `SNES` context
48849b94acceSBarry Smith 
4885d8d19677SJose E. Roman    Output Parameters:
4886dc4c0fb0SBarry Smith +  r - the vector that is used to store residuals (or `NULL` if you don't want it)
488720f4b53cSBarry Smith .  f - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunction`
4888dc4c0fb0SBarry Smith -  ctx - the function context (or `NULL` if you don't want it)
48899b94acceSBarry Smith 
489036851e7fSLois Curfman McInnes    Level: advanced
489136851e7fSLois Curfman McInnes 
4892f6dfbefdSBarry Smith     Note:
4893dc4c0fb0SBarry Smith    The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
489404edfde5SBarry Smith 
48951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction`
48969b94acceSBarry Smith @*/
4897d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4898d71ae5a4SJacob Faibussowitsch {
48996cab3a1bSJed Brown   DM dm;
4900a63bb30eSJed Brown 
49013a40ed3dSBarry Smith   PetscFunctionBegin;
49020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4903a63bb30eSJed Brown   if (r) {
4904a63bb30eSJed Brown     if (!snes->vec_func) {
4905a63bb30eSJed Brown       if (snes->vec_rhs) {
49069566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
4907a63bb30eSJed Brown       } else if (snes->vec_sol) {
49089566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
4909a63bb30eSJed Brown       } else if (snes->dm) {
49109566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
4911a63bb30eSJed Brown       }
4912a63bb30eSJed Brown     }
4913a63bb30eSJed Brown     *r = snes->vec_func;
4914a63bb30eSJed Brown   }
49159566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49169566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
49173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49189b94acceSBarry Smith }
49199b94acceSBarry Smith 
4920c79ef259SPeter Brune /*@C
492137fdd005SBarry Smith    SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
4922c79ef259SPeter Brune 
4923c79ef259SPeter Brune    Input Parameter:
4924f6dfbefdSBarry Smith .  snes - the `SNES` context
4925c79ef259SPeter Brune 
4926d8d19677SJose E. Roman    Output Parameters:
492737fdd005SBarry Smith +  f - the function (or `NULL`) see `SNESSetNGS()` for details
4928dc4c0fb0SBarry Smith -  ctx    - the function context (or `NULL`)
4929c79ef259SPeter Brune 
4930c79ef259SPeter Brune    Level: advanced
4931c79ef259SPeter Brune 
49321cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`
4933c79ef259SPeter Brune @*/
4934c79ef259SPeter Brune 
4935d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4936d71ae5a4SJacob Faibussowitsch {
49376cab3a1bSJed Brown   DM dm;
49386cab3a1bSJed Brown 
4939646217ecSPeter Brune   PetscFunctionBegin;
4940646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49419566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49429566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
49433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4944646217ecSPeter Brune }
4945646217ecSPeter Brune 
49463c7409f5SSatish Balay /*@C
49473c7409f5SSatish Balay    SNESSetOptionsPrefix - Sets the prefix used for searching for all
4948f6dfbefdSBarry Smith    `SNES` options in the database.
49493c7409f5SSatish Balay 
4950c3339decSBarry Smith    Logically Collective
4951fee21e36SBarry Smith 
4952d8d19677SJose E. Roman    Input Parameters:
4953f6dfbefdSBarry Smith +  snes - the `SNES` context
4954c7afd0dbSLois Curfman McInnes -  prefix - the prefix to prepend to all option names
4955c7afd0dbSLois Curfman McInnes 
4956dc4c0fb0SBarry Smith    Level: advanced
4957dc4c0fb0SBarry Smith 
4958f6dfbefdSBarry Smith    Note:
4959a83b1b31SSatish Balay    A hyphen (-) must NOT be given at the beginning of the prefix name.
4960c7afd0dbSLois Curfman McInnes    The first character of all runtime options is AUTOMATICALLY the hyphen.
4961d850072dSLois Curfman McInnes 
49621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
49633c7409f5SSatish Balay @*/
4964d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
4965d71ae5a4SJacob Faibussowitsch {
49663a40ed3dSBarry Smith   PetscFunctionBegin;
49670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49689566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
49699566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
497035f5d045SPeter Brune   if (snes->linesearch) {
49719566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
49729566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
497335f5d045SPeter Brune   }
49749566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
49753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49763c7409f5SSatish Balay }
49773c7409f5SSatish Balay 
49783c7409f5SSatish Balay /*@C
4979f525115eSLois Curfman McInnes    SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
4980f6dfbefdSBarry Smith    `SNES` options in the database.
49813c7409f5SSatish Balay 
4982c3339decSBarry Smith    Logically Collective
4983fee21e36SBarry Smith 
4984c7afd0dbSLois Curfman McInnes    Input Parameters:
4985f6dfbefdSBarry Smith +  snes - the `SNES` context
4986c7afd0dbSLois Curfman McInnes -  prefix - the prefix to prepend to all option names
4987c7afd0dbSLois Curfman McInnes 
4988dc4c0fb0SBarry Smith    Level: advanced
4989dc4c0fb0SBarry Smith 
4990f6dfbefdSBarry Smith    Note:
4991a83b1b31SSatish Balay    A hyphen (-) must NOT be given at the beginning of the prefix name.
4992c7afd0dbSLois Curfman McInnes    The first character of all runtime options is AUTOMATICALLY the hyphen.
4993d850072dSLois Curfman McInnes 
49941cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
49953c7409f5SSatish Balay @*/
4996d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
4997d71ae5a4SJacob Faibussowitsch {
49983a40ed3dSBarry Smith   PetscFunctionBegin;
49990700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50009566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
50019566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
500235f5d045SPeter Brune   if (snes->linesearch) {
50039566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50049566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
500535f5d045SPeter Brune   }
50069566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
50073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50083c7409f5SSatish Balay }
50093c7409f5SSatish Balay 
50109ab63eb5SSatish Balay /*@C
5011f6dfbefdSBarry Smith    SNESGetOptionsPrefix - Gets the prefix used for searching for all
5012f6dfbefdSBarry Smith    `SNES` options in the database.
50133c7409f5SSatish Balay 
5014c7afd0dbSLois Curfman McInnes    Not Collective
5015c7afd0dbSLois Curfman McInnes 
50163c7409f5SSatish Balay    Input Parameter:
5017f6dfbefdSBarry Smith .  snes - the `SNES` context
50183c7409f5SSatish Balay 
50193c7409f5SSatish Balay    Output Parameter:
50203c7409f5SSatish Balay .  prefix - pointer to the prefix string used
50213c7409f5SSatish Balay 
502236851e7fSLois Curfman McInnes    Level: advanced
502336851e7fSLois Curfman McInnes 
5024dc4c0fb0SBarry Smith    Fortran Note:
5025dc4c0fb0SBarry Smith     The user should pass in a string 'prefix' of
5026dc4c0fb0SBarry Smith    sufficient length to hold the prefix.
5027dc4c0fb0SBarry Smith 
50281cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
50293c7409f5SSatish Balay @*/
5030d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5031d71ae5a4SJacob Faibussowitsch {
50323a40ed3dSBarry Smith   PetscFunctionBegin;
50330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50349566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
50353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50363c7409f5SSatish Balay }
50373c7409f5SSatish Balay 
50383cea93caSBarry Smith /*@C
50391c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
50401c84c290SBarry Smith 
504120f4b53cSBarry Smith    Not Collective
50421c84c290SBarry Smith 
50431c84c290SBarry Smith    Input Parameters:
504420f4b53cSBarry Smith +  sname - name of a new user-defined solver
504520f4b53cSBarry Smith -  function - routine to create method context
50461c84c290SBarry Smith 
5047dc4c0fb0SBarry Smith    Level: advanced
5048dc4c0fb0SBarry Smith 
5049f6dfbefdSBarry Smith    Note:
5050f6dfbefdSBarry Smith    `SNESRegister()` may be called multiple times to add several user-defined solvers.
50511c84c290SBarry Smith 
50521c84c290SBarry Smith    Sample usage:
50531c84c290SBarry Smith .vb
5054bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
50551c84c290SBarry Smith .ve
50561c84c290SBarry Smith 
50571c84c290SBarry Smith    Then, your solver can be chosen with the procedural interface via
50581c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
50591c84c290SBarry Smith    or at runtime via the option
50601c84c290SBarry Smith $     -snes_type my_solver
50611c84c290SBarry Smith 
50621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
50633cea93caSBarry Smith @*/
5064d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5065d71ae5a4SJacob Faibussowitsch {
5066b2002411SLois Curfman McInnes   PetscFunctionBegin;
50679566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
50689566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
50693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5070b2002411SLois Curfman McInnes }
5071da9b6338SBarry Smith 
5072d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5073d71ae5a4SJacob Faibussowitsch {
507477431f27SBarry Smith   PetscInt    N, i, j;
5075da9b6338SBarry Smith   Vec         u, uh, fh;
5076da9b6338SBarry Smith   PetscScalar value;
5077da9b6338SBarry Smith   PetscReal   norm;
5078da9b6338SBarry Smith 
5079da9b6338SBarry Smith   PetscFunctionBegin;
50809566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
50819566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
50829566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5083da9b6338SBarry Smith 
5084da9b6338SBarry Smith   /* currently only works for sequential */
50859566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
50869566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5087da9b6338SBarry Smith   for (i = 0; i < N; i++) {
50889566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
508963a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5090da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
50918b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
50929566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
50939566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
50949566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
509563a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5096da9b6338SBarry Smith       value = -value;
50979566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5098da9b6338SBarry Smith     }
5099da9b6338SBarry Smith   }
51009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
51019566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
51023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5103da9b6338SBarry Smith }
510471f87433Sdalcinl 
510571f87433Sdalcinl /*@
5106f6dfbefdSBarry Smith    SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
510771f87433Sdalcinl    computing relative tolerance for linear solvers within an inexact
510871f87433Sdalcinl    Newton method.
510971f87433Sdalcinl 
5110c3339decSBarry Smith    Logically Collective
511171f87433Sdalcinl 
511271f87433Sdalcinl    Input Parameters:
5113f6dfbefdSBarry Smith +  snes - `SNES` context
5114f6dfbefdSBarry Smith -  flag - `PETSC_TRUE` or `PETSC_FALSE`
511571f87433Sdalcinl 
5116f6dfbefdSBarry Smith     Options Database Keys:
511764ba62caSBarry Smith +  -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
511864ba62caSBarry Smith .  -snes_ksp_ew_version ver - version of  Eisenstat-Walker method
511964ba62caSBarry Smith .  -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
512064ba62caSBarry Smith .  -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
512164ba62caSBarry Smith .  -snes_ksp_ew_gamma <gamma> - Sets gamma
512264ba62caSBarry Smith .  -snes_ksp_ew_alpha <alpha> - Sets alpha
512364ba62caSBarry Smith .  -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
512464ba62caSBarry Smith -  -snes_ksp_ew_threshold <threshold> - Sets threshold
512564ba62caSBarry Smith 
5126dc4c0fb0SBarry Smith    Level: advanced
5127dc4c0fb0SBarry Smith 
5128f6dfbefdSBarry Smith    Note:
5129f6dfbefdSBarry Smith    The default is to use a constant relative tolerance for
513071f87433Sdalcinl    the inner linear solvers.  Alternatively, one can use the
513171f87433Sdalcinl    Eisenstat-Walker method, where the relative convergence tolerance
513271f87433Sdalcinl    is reset at each Newton iteration according progress of the nonlinear
513371f87433Sdalcinl    solver.
513471f87433Sdalcinl 
513571f87433Sdalcinl    Reference:
5136f6dfbefdSBarry Smith .  - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996.
513771f87433Sdalcinl 
51381cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
513971f87433Sdalcinl @*/
5140d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5141d71ae5a4SJacob Faibussowitsch {
514271f87433Sdalcinl   PetscFunctionBegin;
51430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5144acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
514571f87433Sdalcinl   snes->ksp_ewconv = flag;
51463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
514771f87433Sdalcinl }
514871f87433Sdalcinl 
514971f87433Sdalcinl /*@
5150f6dfbefdSBarry Smith    SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
515171f87433Sdalcinl    for computing relative tolerance for linear solvers within an
515271f87433Sdalcinl    inexact Newton method.
515371f87433Sdalcinl 
515471f87433Sdalcinl    Not Collective
515571f87433Sdalcinl 
515671f87433Sdalcinl    Input Parameter:
5157f6dfbefdSBarry Smith .  snes - `SNES` context
515871f87433Sdalcinl 
515971f87433Sdalcinl    Output Parameter:
5160f6dfbefdSBarry Smith .  flag - `PETSC_TRUE` or `PETSC_FALSE`
516171f87433Sdalcinl 
516271f87433Sdalcinl    Level: advanced
516371f87433Sdalcinl 
51641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
516571f87433Sdalcinl @*/
5166d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5167d71ae5a4SJacob Faibussowitsch {
516871f87433Sdalcinl   PetscFunctionBegin;
51690700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5170534a8f05SLisandro Dalcin   PetscValidBoolPointer(flag, 2);
517171f87433Sdalcinl   *flag = snes->ksp_ewconv;
51723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
517371f87433Sdalcinl }
517471f87433Sdalcinl 
517571f87433Sdalcinl /*@
5176fa9f3622SBarry Smith    SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
517771f87433Sdalcinl    convergence criteria for the linear solvers within an inexact
517871f87433Sdalcinl    Newton method.
517971f87433Sdalcinl 
5180c3339decSBarry Smith    Logically Collective
518171f87433Sdalcinl 
518271f87433Sdalcinl    Input Parameters:
5183f6dfbefdSBarry Smith +    snes - `SNES` context
51840f0abf79SStefano Zampini .    version - version 1, 2 (default is 2), 3 or 4
518571f87433Sdalcinl .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
518671f87433Sdalcinl .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
518771f87433Sdalcinl .    gamma - multiplicative factor for version 2 rtol computation
518871f87433Sdalcinl              (0 <= gamma2 <= 1)
518971f87433Sdalcinl .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
519071f87433Sdalcinl .    alpha2 - power for safeguard
519171f87433Sdalcinl -    threshold - threshold for imposing safeguard (0 < threshold < 1)
519271f87433Sdalcinl 
5193dc4c0fb0SBarry Smith    Level: advanced
5194dc4c0fb0SBarry Smith 
5195f6dfbefdSBarry Smith    Notes:
519671f87433Sdalcinl    Version 3 was contributed by Luis Chacon, June 2006.
519771f87433Sdalcinl 
5198f6dfbefdSBarry Smith    Use `PETSC_DEFAULT` to retain the default for any of the parameters.
519971f87433Sdalcinl 
52001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
520171f87433Sdalcinl @*/
5202d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5203d71ae5a4SJacob Faibussowitsch {
5204fa9f3622SBarry Smith   SNESKSPEW *kctx;
52055fd66863SKarl Rupp 
520671f87433Sdalcinl   PetscFunctionBegin;
52070700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5208fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52095f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5210c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5211c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5212c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5213c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5214c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5215c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5216c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
521771f87433Sdalcinl 
521871f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
521913bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
522013bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
522113bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
522213bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
522313bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
522413bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
522571f87433Sdalcinl 
52260f0abf79SStefano 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);
52270b121fc5SBarry 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);
52280b121fc5SBarry 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);
52290b121fc5SBarry 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);
52300b121fc5SBarry 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);
52310b121fc5SBarry 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);
52323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
523371f87433Sdalcinl }
523471f87433Sdalcinl 
523571f87433Sdalcinl /*@
5236fa9f3622SBarry Smith    SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
523771f87433Sdalcinl    convergence criteria for the linear solvers within an inexact
523871f87433Sdalcinl    Newton method.
523971f87433Sdalcinl 
524071f87433Sdalcinl    Not Collective
524171f87433Sdalcinl 
524297bb3fdcSJose E. Roman    Input Parameter:
5243f6dfbefdSBarry Smith .    snes - `SNES` context
524471f87433Sdalcinl 
524571f87433Sdalcinl    Output Parameters:
52460f0abf79SStefano Zampini +    version - version 1, 2 (default is 2), 3 or 4
524771f87433Sdalcinl .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
524871f87433Sdalcinl .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
5249bf388a1fSBarry Smith .    gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
525071f87433Sdalcinl .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
525171f87433Sdalcinl .    alpha2 - power for safeguard
525271f87433Sdalcinl -    threshold - threshold for imposing safeguard (0 < threshold < 1)
525371f87433Sdalcinl 
525471f87433Sdalcinl    Level: advanced
525571f87433Sdalcinl 
52561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
525771f87433Sdalcinl @*/
5258d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5259d71ae5a4SJacob Faibussowitsch {
5260fa9f3622SBarry Smith   SNESKSPEW *kctx;
52615fd66863SKarl Rupp 
526271f87433Sdalcinl   PetscFunctionBegin;
52630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5264fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52655f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
526671f87433Sdalcinl   if (version) *version = kctx->version;
526771f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
526871f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
526971f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
527071f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
527171f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
527271f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
52733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
527471f87433Sdalcinl }
527571f87433Sdalcinl 
5276d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5277d71ae5a4SJacob Faibussowitsch {
5278fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
527971f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
528071f87433Sdalcinl 
528171f87433Sdalcinl   PetscFunctionBegin;
52823ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
528330058271SDmitry Karpeev   if (!snes->iter) {
528430058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
52859566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
52860f0abf79SStefano Zampini   } else {
52870fdf79fbSJacob 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);
528871f87433Sdalcinl     if (kctx->version == 1) {
52890f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
529085ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
529171f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
529271f87433Sdalcinl     } else if (kctx->version == 2) {
529385ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
529485ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
529571f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
529671f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
529785ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
529871f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
529985ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
530071f87433Sdalcinl       stol = PetscMax(rtol, stol);
530171f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
530271f87433Sdalcinl       /* safeguard: avoid oversolving */
530330058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
530471f87433Sdalcinl       stol = PetscMax(rtol, stol);
530571f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
53060fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
53070fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
53080f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
53090f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
53100f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
53110f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
53120f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
53130f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
53140f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
53150f0abf79SStefano Zampini 
5316a4598233SStefano 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;
53170f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
53180f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
53190f0abf79SStefano Zampini       kctx->rk_last     = rk;
53200fdf79fbSJacob Faibussowitsch     }
53210f0abf79SStefano Zampini   }
53220f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
532371f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
53249566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
532563a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
53263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
532771f87433Sdalcinl }
532871f87433Sdalcinl 
5329d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5330d71ae5a4SJacob Faibussowitsch {
5331fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
533271f87433Sdalcinl   PCSide     pcside;
533371f87433Sdalcinl   Vec        lres;
533471f87433Sdalcinl 
533571f87433Sdalcinl   PetscFunctionBegin;
53363ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
53379566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
533871dbe336SPeter Brune   kctx->norm_last = snes->norm;
53390f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
53404f00ce20SMatthew G. Knepley     PC        pc;
53410f0abf79SStefano Zampini     PetscBool getRes;
53424f00ce20SMatthew G. Knepley 
53439566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
53440f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
53450f0abf79SStefano Zampini     if (!getRes) {
53460f0abf79SStefano Zampini       KSPNormType normtype;
53470f0abf79SStefano Zampini 
53480f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
53490f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
53500f0abf79SStefano Zampini     }
53519566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
53520f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
53539566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
535471f87433Sdalcinl     } else {
535571f87433Sdalcinl       /* KSP residual is preconditioned residual */
535671f87433Sdalcinl       /* compute true linear residual norm */
53570f0abf79SStefano Zampini       Mat J;
53580f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
53599566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
53600f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
53619566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
53629566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
53639566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
536471f87433Sdalcinl     }
536571f87433Sdalcinl   }
53663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536771f87433Sdalcinl }
536871f87433Sdalcinl 
5369d4211eb9SBarry Smith /*@
5370f6dfbefdSBarry Smith    SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5371d4211eb9SBarry Smith 
5372f6dfbefdSBarry Smith    Not Collective, but if snes is parallel, then ksp is parallel
5373d4211eb9SBarry Smith 
5374d4211eb9SBarry Smith    Input Parameter:
5375f6dfbefdSBarry Smith .  snes - the `SNES` context
5376d4211eb9SBarry Smith 
5377d4211eb9SBarry Smith    Output Parameter:
5378f6dfbefdSBarry Smith .  ksp - the `KSP` context
5379d4211eb9SBarry Smith 
5380dc4c0fb0SBarry Smith    Level: beginner
5381dc4c0fb0SBarry Smith 
5382d4211eb9SBarry Smith    Notes:
5383f6dfbefdSBarry Smith    The user can then directly manipulate the `KSP` context to set various
5384d4211eb9SBarry Smith    options, etc.  Likewise, the user can then extract and manipulate the
5385f6dfbefdSBarry Smith    `PC` contexts as well.
5386f6dfbefdSBarry Smith 
5387f6dfbefdSBarry Smith    Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5388d4211eb9SBarry Smith 
53891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5390d4211eb9SBarry Smith @*/
5391d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5392d71ae5a4SJacob Faibussowitsch {
539371f87433Sdalcinl   PetscFunctionBegin;
5394d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5395d4211eb9SBarry Smith   PetscValidPointer(ksp, 2);
5396d4211eb9SBarry Smith 
5397d4211eb9SBarry Smith   if (!snes->ksp) {
53989566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
53999566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5400d4211eb9SBarry Smith 
54019566063dSJacob Faibussowitsch     PetscCall(KSPSetPreSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_SNESEW, snes));
54029566063dSJacob Faibussowitsch     PetscCall(KSPSetPostSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_SNESEW, snes));
5403a5c2985bSBarry Smith 
54049566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
54059566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5406d4211eb9SBarry Smith   }
5407d4211eb9SBarry Smith   *ksp = snes->ksp;
54083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
540971f87433Sdalcinl }
54106c699258SBarry Smith 
5411af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
54126c699258SBarry Smith /*@
5413f6dfbefdSBarry Smith    SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
54146c699258SBarry Smith 
5415c3339decSBarry Smith    Logically Collective
54166c699258SBarry Smith 
54176c699258SBarry Smith    Input Parameters:
54182a808120SBarry Smith +  snes - the nonlinear solver context
5419dc4c0fb0SBarry Smith -  dm - the dm, cannot be `NULL`
5420dc4c0fb0SBarry Smith 
5421dc4c0fb0SBarry Smith    Level: intermediate
54226c699258SBarry Smith 
5423f6dfbefdSBarry Smith    Note:
5424f6dfbefdSBarry Smith    A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5425f6dfbefdSBarry Smith    even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5426e03a659cSJed Brown    problems using the same function space.
5427e03a659cSJed Brown 
54281cc06b55SBarry Smith .seealso: [](ch_snes), `DM`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
54296c699258SBarry Smith @*/
5430d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5431d71ae5a4SJacob Faibussowitsch {
5432345fed2cSBarry Smith   KSP    ksp;
5433942e3340SBarry Smith   DMSNES sdm;
54346c699258SBarry Smith 
54356c699258SBarry Smith   PetscFunctionBegin;
54360700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54372a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
54389566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5439942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
544051f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
54419566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
54429566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5443f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
54446cab3a1bSJed Brown     }
54459566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
54469566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
54476cab3a1bSJed Brown   }
54486c699258SBarry Smith   snes->dm     = dm;
5449116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5450f5af7f23SKarl Rupp 
54519566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
54529566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
54539566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5454efd4aadfSBarry Smith   if (snes->npc) {
54559566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
54569566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
54572c155ee1SBarry Smith   }
54583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54596c699258SBarry Smith }
54606c699258SBarry Smith 
54616c699258SBarry Smith /*@
5462f6dfbefdSBarry Smith    SNESGetDM - Gets the `DM` that may be used by some preconditioners
54636c699258SBarry Smith 
5464f6dfbefdSBarry Smith    Not Collective but dm obtained is parallel on snes
54656c699258SBarry Smith 
54666c699258SBarry Smith    Input Parameter:
54676c699258SBarry Smith . snes - the preconditioner context
54686c699258SBarry Smith 
54696c699258SBarry Smith    Output Parameter:
54706c699258SBarry Smith .  dm - the dm
54716c699258SBarry Smith 
54726c699258SBarry Smith    Level: intermediate
54736c699258SBarry Smith 
54741cc06b55SBarry Smith .seealso: [](ch_snes), `DM`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
54756c699258SBarry Smith @*/
5476d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5477d71ae5a4SJacob Faibussowitsch {
54786c699258SBarry Smith   PetscFunctionBegin;
54790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54806cab3a1bSJed Brown   if (!snes->dm) {
54819566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5482116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
54836cab3a1bSJed Brown   }
54846c699258SBarry Smith   *dm = snes->dm;
54853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54866c699258SBarry Smith }
54870807856dSBarry Smith 
548831823bd8SMatthew G Knepley /*@
5489be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
549031823bd8SMatthew G Knepley 
5491c3339decSBarry Smith   Collective
549231823bd8SMatthew G Knepley 
549331823bd8SMatthew G Knepley   Input Parameters:
5494f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5495f6dfbefdSBarry Smith - npc   - the preconditioner object
549631823bd8SMatthew G Knepley 
5497dc4c0fb0SBarry Smith   Level: developer
5498dc4c0fb0SBarry Smith 
549931823bd8SMatthew G Knepley   Notes:
5500f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
550131823bd8SMatthew G Knepley   to configure it using the API).
550231823bd8SMatthew G Knepley 
5503f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5504f6dfbefdSBarry Smith 
55051cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
550631823bd8SMatthew G Knepley @*/
5507d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5508d71ae5a4SJacob Faibussowitsch {
550931823bd8SMatthew G Knepley   PetscFunctionBegin;
551031823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5511f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5512f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5513f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
55149566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5515f6dfbefdSBarry Smith   snes->npc = npc;
55163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
551731823bd8SMatthew G Knepley }
551831823bd8SMatthew G Knepley 
551931823bd8SMatthew G Knepley /*@
5520f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
552131823bd8SMatthew G Knepley 
5522f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
552331823bd8SMatthew G Knepley 
552431823bd8SMatthew G Knepley   Input Parameter:
5525f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
552631823bd8SMatthew G Knepley 
552731823bd8SMatthew G Knepley   Output Parameter:
5528f6dfbefdSBarry Smith . npc - preconditioner context
552931823bd8SMatthew G Knepley 
5530f6dfbefdSBarry Smith   Options Database Key:
5531f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5532b5badacbSBarry Smith 
5533dc4c0fb0SBarry Smith   Level: developer
5534dc4c0fb0SBarry Smith 
553595452b02SPatrick Sanan   Notes:
5536f6dfbefdSBarry Smith     If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5537be95d8f1SBarry Smith 
5538f6dfbefdSBarry Smith     The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5539f6dfbefdSBarry Smith     `SNES`
5540951fe5abSBarry Smith 
55411cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
554231823bd8SMatthew G Knepley @*/
5543d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5544d71ae5a4SJacob Faibussowitsch {
5545a64e098fSPeter Brune   const char *optionsprefix;
554631823bd8SMatthew G Knepley 
554731823bd8SMatthew G Knepley   PetscFunctionBegin;
554831823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
554931823bd8SMatthew G Knepley   PetscValidPointer(pc, 2);
5550efd4aadfSBarry Smith   if (!snes->npc) {
5551ec785e5bSStefano Zampini     void *ctx;
5552ec785e5bSStefano Zampini 
55539566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
55549566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
55559566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
55569566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
55579566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5558ec785e5bSStefano Zampini     PetscCall(SNESGetApplicationContext(snes, &ctx));
5559ec785e5bSStefano Zampini     PetscCall(SNESSetApplicationContext(snes->npc, ctx));
55609566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
556131823bd8SMatthew G Knepley   }
5562efd4aadfSBarry Smith   *pc = snes->npc;
55633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
556431823bd8SMatthew G Knepley }
556531823bd8SMatthew G Knepley 
55663ad1a0b9SPatrick Farrell /*@
55673ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
55683ad1a0b9SPatrick Farrell 
55693ad1a0b9SPatrick Farrell   Not Collective
55703ad1a0b9SPatrick Farrell 
55713ad1a0b9SPatrick Farrell   Input Parameter:
5572f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
55733ad1a0b9SPatrick Farrell 
55743ad1a0b9SPatrick Farrell   Output Parameter:
5575f6dfbefdSBarry Smith . has_npc - whether the `SNES` has an NPC or not
55763ad1a0b9SPatrick Farrell 
55773ad1a0b9SPatrick Farrell   Level: developer
55783ad1a0b9SPatrick Farrell 
55791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
55803ad1a0b9SPatrick Farrell @*/
5581d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5582d71ae5a4SJacob Faibussowitsch {
55833ad1a0b9SPatrick Farrell   PetscFunctionBegin;
55843ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5585efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
55863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55873ad1a0b9SPatrick Farrell }
55883ad1a0b9SPatrick Farrell 
5589c40d0f55SPeter Brune /*@
5590be95d8f1SBarry Smith     SNESSetNPCSide - Sets the preconditioning side.
5591c40d0f55SPeter Brune 
5592c3339decSBarry Smith     Logically Collective
5593c40d0f55SPeter Brune 
5594c40d0f55SPeter Brune     Input Parameter:
5595f6dfbefdSBarry Smith .   snes - iterative context obtained from `SNESCreate()`
5596c40d0f55SPeter Brune 
5597c40d0f55SPeter Brune     Output Parameter:
5598c40d0f55SPeter Brune .   side - the preconditioning side, where side is one of
5599c40d0f55SPeter Brune .vb
56002d547940SBarry Smith       PC_LEFT - left preconditioning
56012d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5602c40d0f55SPeter Brune .ve
5603c40d0f55SPeter Brune 
5604f6dfbefdSBarry Smith     Options Database Key:
560567b8a455SSatish Balay .   -snes_npc_side <right,left> - nonlinear preconditioner side
5606c40d0f55SPeter Brune 
5607dc4c0fb0SBarry Smith     Level: intermediate
5608dc4c0fb0SBarry Smith 
5609f6dfbefdSBarry Smith     Note:
5610f6dfbefdSBarry Smith     `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
56112d547940SBarry Smith 
56121cc06b55SBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`
5613c40d0f55SPeter Brune @*/
5614d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5615d71ae5a4SJacob Faibussowitsch {
5616c40d0f55SPeter Brune   PetscFunctionBegin;
5617c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5618c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5619b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
562054c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5621efd4aadfSBarry Smith   snes->npcside = side;
56223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5623c40d0f55SPeter Brune }
5624c40d0f55SPeter Brune 
5625c40d0f55SPeter Brune /*@
5626be95d8f1SBarry Smith     SNESGetNPCSide - Gets the preconditioning side.
5627c40d0f55SPeter Brune 
5628c40d0f55SPeter Brune     Not Collective
5629c40d0f55SPeter Brune 
5630c40d0f55SPeter Brune     Input Parameter:
5631f6dfbefdSBarry Smith .   snes - iterative context obtained from `SNESCreate()`
5632c40d0f55SPeter Brune 
5633c40d0f55SPeter Brune     Output Parameter:
5634c40d0f55SPeter Brune .   side - the preconditioning side, where side is one of
5635c40d0f55SPeter Brune .vb
5636f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5637f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5638c40d0f55SPeter Brune .ve
5639c40d0f55SPeter Brune 
5640c40d0f55SPeter Brune     Level: intermediate
5641c40d0f55SPeter Brune 
56421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`
5643c40d0f55SPeter Brune @*/
5644d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5645d71ae5a4SJacob Faibussowitsch {
5646c40d0f55SPeter Brune   PetscFunctionBegin;
5647c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5648c40d0f55SPeter Brune   PetscValidPointer(side, 2);
5649efd4aadfSBarry Smith   *side = snes->npcside;
56503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5651c40d0f55SPeter Brune }
5652c40d0f55SPeter Brune 
56539e764e56SPeter Brune /*@
5654f6dfbefdSBarry Smith   SNESSetLineSearch - Sets the linesearch on the `SNES` instance.
56559e764e56SPeter Brune 
5656c3339decSBarry Smith   Collective
56579e764e56SPeter Brune 
56589e764e56SPeter Brune   Input Parameters:
5659f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
56609e764e56SPeter Brune - linesearch   - the linesearch object
56619e764e56SPeter Brune 
5662dc4c0fb0SBarry Smith   Level: developer
5663dc4c0fb0SBarry Smith 
5664f6dfbefdSBarry Smith   Note:
5665f6dfbefdSBarry Smith   Use `SNESGetLineSearch()` to retrieve the preconditioner context (for example,
56669e764e56SPeter Brune   to configure it using the API).
56679e764e56SPeter Brune 
56681cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLineSearch()`
56699e764e56SPeter Brune @*/
5670d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5671d71ae5a4SJacob Faibussowitsch {
56729e764e56SPeter Brune   PetscFunctionBegin;
56739e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5674f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
56759e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
56769566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
56779566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5678f5af7f23SKarl Rupp 
56799e764e56SPeter Brune   snes->linesearch = linesearch;
5680f5af7f23SKarl Rupp 
56813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56829e764e56SPeter Brune }
56839e764e56SPeter Brune 
5684a34ceb2aSJed Brown /*@
5685dc4c0fb0SBarry Smith   SNESGetLineSearch - Returns the line search context set with `SNESSetLineSearch()`
5686f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
56879e764e56SPeter Brune 
56889e764e56SPeter Brune   Not Collective
56899e764e56SPeter Brune 
56909e764e56SPeter Brune   Input Parameter:
5691f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56929e764e56SPeter Brune 
56939e764e56SPeter Brune   Output Parameter:
56949e764e56SPeter Brune . linesearch - linesearch context
56959e764e56SPeter Brune 
5696162e0bf5SPeter Brune   Level: beginner
56979e764e56SPeter Brune 
56981cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
56999e764e56SPeter Brune @*/
5700d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5701d71ae5a4SJacob Faibussowitsch {
57029e764e56SPeter Brune   const char *optionsprefix;
57039e764e56SPeter Brune 
57049e764e56SPeter Brune   PetscFunctionBegin;
57059e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57069e764e56SPeter Brune   PetscValidPointer(linesearch, 2);
57079e764e56SPeter Brune   if (!snes->linesearch) {
57089566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57099566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
57109566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
57119566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
57129566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
57139e764e56SPeter Brune   }
57149e764e56SPeter Brune   *linesearch = snes->linesearch;
57153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57169e764e56SPeter Brune }
5717