xref: /petsc/src/snes/interface/snes.c (revision 9b5c1c089cedcbce7788b211145051d6cc715929)
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;
13e3ed9ee7SBarry Smith PetscLogEvent SNES_Solve, SNES_Setup, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval;
14a09944afSBarry Smith 
15e113a28aSBarry Smith /*@
16f6dfbefdSBarry Smith    SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error 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 
24e113a28aSBarry Smith    Options database keys:
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 
33f6dfbefdSBarry Smith .seealso: `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;
41e113a28aSBarry Smith   PetscFunctionReturn(0);
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 
57f6dfbefdSBarry Smith .seealso: `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;
65e113a28aSBarry Smith   PetscFunctionReturn(0);
66e113a28aSBarry Smith }
67e113a28aSBarry Smith 
684fc747eaSLawrence Mitchell /*@
69f6dfbefdSBarry Smith     SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual 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 
83f6dfbefdSBarry Smith .seealso: `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;
904fc747eaSLawrence Mitchell   PetscFunctionReturn(0);
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 
106f6dfbefdSBarry Smith .seealso: `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;
1134fc747eaSLawrence Mitchell   PetscFunctionReturn(0);
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 
1224936397dSBarry Smith    Input Parameters:
123f6dfbefdSBarry Smith .  snes - the `SNES` context
1244936397dSBarry Smith 
12528529972SSatish Balay    Level: advanced
1264936397dSBarry Smith 
127f0b84518SBarry Smith    Note:
128f0b84518SBarry Smith    You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
129f0b84518SBarry Smith    `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
130f0b84518SBarry Smith 
131f0b84518SBarry Smith .seealso: `SNESCreate()`, `SNESSetFunction()`, `SNESFunction`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
132f0b84518SBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
1334936397dSBarry Smith @*/
134d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes)
135d71ae5a4SJacob Faibussowitsch {
1364936397dSBarry Smith   PetscFunctionBegin;
1370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1385f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain");
1394936397dSBarry Smith   snes->domainerror = PETSC_TRUE;
1404936397dSBarry Smith   PetscFunctionReturn(0);
1414936397dSBarry Smith }
1424936397dSBarry Smith 
1436a388c36SPeter Brune /*@
144f6dfbefdSBarry Smith    SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation.
14507b62357SFande Kong 
146c3339decSBarry Smith    Logically Collective
14707b62357SFande Kong 
14807b62357SFande Kong    Input Parameters:
149f6dfbefdSBarry Smith .  snes - the `SNES` context
15007b62357SFande Kong 
15107b62357SFande Kong    Level: advanced
15207b62357SFande Kong 
153f0b84518SBarry Smith    Note:
154f0b84518SBarry Smith    You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
155f0b84518SBarry Smith    `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
156f0b84518SBarry Smith 
157f0b84518SBarry Smith .seealso: `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`,
158f0b84518SBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
15907b62357SFande Kong @*/
160d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes)
161d71ae5a4SJacob Faibussowitsch {
16207b62357SFande Kong   PetscFunctionBegin;
16307b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1645f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense");
16507b62357SFande Kong   snes->jacobiandomainerror = PETSC_TRUE;
16607b62357SFande Kong   PetscFunctionReturn(0);
16707b62357SFande Kong }
16807b62357SFande Kong 
16907b62357SFande Kong /*@
170f6dfbefdSBarry Smith    SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after
171f6dfbefdSBarry Smith    each Jacobian evaluation. By default, we check Jacobian domain error in the debug mode, and do not check it in the optimized mode.
172b351a90bSFande Kong 
173c3339decSBarry Smith    Logically Collective
174b351a90bSFande Kong 
175b351a90bSFande Kong    Input Parameters:
176a2b725a8SWilliam Gropp +  snes - the SNES context
177f6dfbefdSBarry Smith -  flg  - indicates if or not to check Jacobian domain error after each Jacobian evaluation
178b351a90bSFande Kong 
179b351a90bSFande Kong    Level: advanced
180b351a90bSFande Kong 
181f6dfbefdSBarry Smith    Note:
182f6dfbefdSBarry Smith    Checks require one extra parallel synchronization for each Jacobian evaluation
183f6dfbefdSBarry Smith 
184db781477SPatrick Sanan .seealso: `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()`
185b351a90bSFande Kong @*/
186d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
187d71ae5a4SJacob Faibussowitsch {
188b351a90bSFande Kong   PetscFunctionBegin;
189b351a90bSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
190b351a90bSFande Kong   snes->checkjacdomainerror = flg;
191b351a90bSFande Kong   PetscFunctionReturn(0);
192b351a90bSFande Kong }
193b351a90bSFande Kong 
194b351a90bSFande Kong /*@
1958383d7d7SFande Kong    SNESGetCheckJacobianDomainError - Get an indicator whether or not we are checking Jacobian domain errors after each Jacobian evaluation.
1968383d7d7SFande Kong 
197c3339decSBarry Smith    Logically Collective
1988383d7d7SFande Kong 
1998383d7d7SFande Kong    Input Parameters:
200f6dfbefdSBarry Smith .  snes - the `SNES` context
2018383d7d7SFande Kong 
2028383d7d7SFande Kong    Output Parameters:
203f6dfbefdSBarry Smith .  flg  - `PETSC_FALSE` indicates that we don't check Jacobian domain errors after each Jacobian evaluation
2048383d7d7SFande Kong 
2058383d7d7SFande Kong    Level: advanced
2068383d7d7SFande Kong 
207db781477SPatrick Sanan .seealso: `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()`
2088383d7d7SFande Kong @*/
209d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
210d71ae5a4SJacob Faibussowitsch {
2118383d7d7SFande Kong   PetscFunctionBegin;
2128383d7d7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
213534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
2148383d7d7SFande Kong   *flg = snes->checkjacdomainerror;
2158383d7d7SFande Kong   PetscFunctionReturn(0);
2168383d7d7SFande Kong }
2178383d7d7SFande Kong 
2188383d7d7SFande Kong /*@
219f6dfbefdSBarry Smith    SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()`;
2206a388c36SPeter Brune 
221f6dfbefdSBarry Smith    Logically Collective
2226a388c36SPeter Brune 
2236a388c36SPeter Brune    Input Parameters:
224f6dfbefdSBarry Smith .  snes - the `SNES` context
2256a388c36SPeter Brune 
2266a388c36SPeter Brune    Output Parameters:
227f6dfbefdSBarry Smith .  domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise.
2286a388c36SPeter Brune 
229f6dfbefdSBarry Smith    Level: developer
2306a388c36SPeter Brune 
231db781477SPatrick Sanan .seealso: `SNESSetFunctionDomainError()`, `SNESComputeFunction()`
2326a388c36SPeter Brune @*/
233d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
234d71ae5a4SJacob Faibussowitsch {
2356a388c36SPeter Brune   PetscFunctionBegin;
2366a388c36SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
237534a8f05SLisandro Dalcin   PetscValidBoolPointer(domainerror, 2);
2386a388c36SPeter Brune   *domainerror = snes->domainerror;
2396a388c36SPeter Brune   PetscFunctionReturn(0);
2406a388c36SPeter Brune }
2416a388c36SPeter Brune 
24207b62357SFande Kong /*@
243f6dfbefdSBarry Smith    SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()`;
24407b62357SFande Kong 
245c3339decSBarry Smith    Logically Collective
24607b62357SFande Kong 
24707b62357SFande Kong    Input Parameters:
248f6dfbefdSBarry Smith .  snes - the `SNES` context
24907b62357SFande Kong 
25007b62357SFande Kong    Output Parameters:
251f6dfbefdSBarry Smith .  domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise.
25207b62357SFande Kong 
25307b62357SFande Kong    Level: advanced
25407b62357SFande Kong 
255c2e3fba1SPatrick Sanan .seealso: `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()`
25607b62357SFande Kong @*/
257d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror)
258d71ae5a4SJacob Faibussowitsch {
25907b62357SFande Kong   PetscFunctionBegin;
26007b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
261534a8f05SLisandro Dalcin   PetscValidBoolPointer(domainerror, 2);
26207b62357SFande Kong   *domainerror = snes->jacobiandomainerror;
26307b62357SFande Kong   PetscFunctionReturn(0);
26407b62357SFande Kong }
26507b62357SFande Kong 
26655849f57SBarry Smith /*@C
267f6dfbefdSBarry Smith   SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
26855849f57SBarry Smith 
269c3339decSBarry Smith   Collective
27055849f57SBarry Smith 
27155849f57SBarry Smith   Input Parameters:
272f6dfbefdSBarry Smith + newdm - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
273f6dfbefdSBarry Smith            some related function before a call to `SNESLoad()`.
274f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
27555849f57SBarry Smith 
27655849f57SBarry Smith    Level: intermediate
27755849f57SBarry Smith 
278f6dfbefdSBarry Smith   Note:
279f6dfbefdSBarry Smith    The type is determined by the data in the file, any type set into the `SNES` before this call is ignored.
28055849f57SBarry Smith 
281f6dfbefdSBarry Smith .seealso: `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
28255849f57SBarry Smith @*/
283d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
284d71ae5a4SJacob Faibussowitsch {
28555849f57SBarry Smith   PetscBool isbinary;
286060da220SMatthew G. Knepley   PetscInt  classid;
28755849f57SBarry Smith   char      type[256];
28855849f57SBarry Smith   KSP       ksp;
2892d53ad75SBarry Smith   DM        dm;
2902d53ad75SBarry Smith   DMSNES    dmsnes;
29155849f57SBarry Smith 
29255849f57SBarry Smith   PetscFunctionBegin;
2932d53ad75SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29455849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
2965f80ce2aSJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
29755849f57SBarry Smith 
2989566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
2995f80ce2aSJacob Faibussowitsch   PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3009566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3019566063dSJacob Faibussowitsch   PetscCall(SNESSetType(snes, type));
302dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, load, viewer);
3039566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3049566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &dmsnes));
3059566063dSJacob Faibussowitsch   PetscCall(DMSNESLoad(dmsnes, viewer));
3069566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
3079566063dSJacob Faibussowitsch   PetscCall(KSPLoad(ksp, viewer));
30855849f57SBarry Smith   PetscFunctionReturn(0);
30955849f57SBarry Smith }
3106a388c36SPeter Brune 
3119804daf3SBarry Smith #include <petscdraw.h>
312e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
313e04113cfSBarry Smith   #include <petscviewersaws.h>
314bfb97211SBarry Smith #endif
3158404b7f3SBarry Smith 
316fe2efc57SMark /*@C
317f6dfbefdSBarry Smith    SNESViewFromOptions - View a `SNES` based on the options database
318fe2efc57SMark 
319c3339decSBarry Smith    Collective
320fe2efc57SMark 
321fe2efc57SMark    Input Parameters:
322f6dfbefdSBarry Smith +  A - the `SNES` context
323736c3998SJose E. Roman .  obj - Optional object
324736c3998SJose E. Roman -  name - command line option
325fe2efc57SMark 
326fe2efc57SMark    Level: intermediate
327f6dfbefdSBarry Smith 
328db781477SPatrick Sanan .seealso: `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
329fe2efc57SMark @*/
330d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
331d71ae5a4SJacob Faibussowitsch {
332fe2efc57SMark   PetscFunctionBegin;
333fe2efc57SMark   PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3349566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
335fe2efc57SMark   PetscFunctionReturn(0);
336fe2efc57SMark }
337fe2efc57SMark 
338789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
339789d8953SBarry Smith 
3407e2c5f70SBarry Smith /*@C
341f6dfbefdSBarry Smith    SNESView - Prints the `SNES` data structure.
3429b94acceSBarry Smith 
343c3339decSBarry Smith    Collective
344fee21e36SBarry Smith 
345c7afd0dbSLois Curfman McInnes    Input Parameters:
346f6dfbefdSBarry Smith +  snes - the `SNES` context
347f6dfbefdSBarry Smith -  viewer - the `PetscViewer`
348c7afd0dbSLois Curfman McInnes 
3499b94acceSBarry Smith    Options Database Key:
350f6dfbefdSBarry Smith .  -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3519b94acceSBarry Smith 
3529b94acceSBarry Smith    Notes:
3539b94acceSBarry Smith    The available visualization contexts include
354f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
355f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
356c8a8ba5cSLois Curfman McInnes          output where only the first processor opens
357c8a8ba5cSLois Curfman McInnes          the file.  All other processors send their
358c8a8ba5cSLois Curfman McInnes          data to the first processor to print.
3599b94acceSBarry Smith 
360052bf0daSPierre Jolivet    The available formats include
361f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
362f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
363052bf0daSPierre Jolivet 
3643e081fefSLois Curfman McInnes    The user can open an alternative visualization context with
365f6dfbefdSBarry Smith    `PetscViewerASCIIOpen()` - output to a specified file.
3669b94acceSBarry Smith 
367f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
368595c91d4SBarry Smith 
36936851e7fSLois Curfman McInnes    Level: beginner
37036851e7fSLois Curfman McInnes 
371f6dfbefdSBarry Smith .seealso: `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3729b94acceSBarry Smith @*/
373d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
374d71ae5a4SJacob Faibussowitsch {
375fa9f3622SBarry Smith   SNESKSPEW     *kctx;
37694b7f48cSBarry Smith   KSP            ksp;
3777f1410a3SPeter Brune   SNESLineSearch linesearch;
37872a02f06SBarry Smith   PetscBool      iascii, isstring, isbinary, isdraw;
3792d53ad75SBarry Smith   DMSNES         dmsnes;
380e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
381536b137fSBarry Smith   PetscBool issaws;
382bfb97211SBarry Smith #endif
3839b94acceSBarry Smith 
3843a40ed3dSBarry Smith   PetscFunctionBegin;
3850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
38648a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
3870700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
388c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, viewer, 2);
38974679c65SBarry Smith 
3909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
3929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
394e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
3959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
396bfb97211SBarry Smith #endif
39732077d6dSBarry Smith   if (iascii) {
398dc0571f2SMatthew G. Knepley     SNESNormSchedule normschedule;
3998404b7f3SBarry Smith     DM               dm;
4008404b7f3SBarry Smith     PetscErrorCode (*cJ)(SNES, Vec, Mat, Mat, void *);
4018404b7f3SBarry Smith     void       *ctx;
402789d8953SBarry Smith     const char *pre = "";
403dc0571f2SMatthew G. Knepley 
4049566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
40548a46eb9SPierre Jolivet     if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  SNES has not been set up so information may be incomplete\n"));
406e7788613SBarry Smith     if (snes->ops->view) {
4079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
408dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, view, viewer);
4099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
4100ef38995SBarry Smith     }
41163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
4129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
41348a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
41463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4159566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4169566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
41748a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4189b94acceSBarry Smith     if (snes->ksp_ewconv) {
419fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4209b94acceSBarry Smith       if (kctx) {
42163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4229566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4239566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4249b94acceSBarry Smith       }
4259b94acceSBarry Smith     }
426eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
428eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
42963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
430eb1f6c34SBarry Smith     }
431eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
433eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
43463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
435eb1f6c34SBarry Smith     }
4369566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4379566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
438789d8953SBarry Smith     if (snes->mf_operator) {
4399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
440789d8953SBarry Smith       pre = "Preconditioning ";
441789d8953SBarry Smith     }
4428404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4448404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
446789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
447789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
448789d8953SBarry Smith       MatFDColoring fdcoloring;
4499566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
450789d8953SBarry Smith       if (fdcoloring) {
4519566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
452789d8953SBarry Smith       } else {
4539566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
454789d8953SBarry Smith       }
455789d8953SBarry Smith     } else if (snes->mf) {
4569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4578404b7f3SBarry Smith     }
4580f5bd95cSBarry Smith   } else if (isstring) {
459317d6ea6SBarry Smith     const char *type;
4609566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4619566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
462dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
46355849f57SBarry Smith   } else if (isbinary) {
46455849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
46555849f57SBarry Smith     MPI_Comm    comm;
46655849f57SBarry Smith     PetscMPIInt rank;
46755849f57SBarry Smith     char        type[256];
46855849f57SBarry Smith 
4699566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4709566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
471dd400576SPatrick Sanan     if (rank == 0) {
4729566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4739566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4749566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
47555849f57SBarry Smith     }
476dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47772a02f06SBarry Smith   } else if (isdraw) {
47872a02f06SBarry Smith     PetscDraw draw;
47972a02f06SBarry Smith     char      str[36];
48089fd9fafSBarry Smith     PetscReal x, y, bottom, h;
48172a02f06SBarry Smith 
4829566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4839566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4849566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4859566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
4869566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
48789fd9fafSBarry Smith     bottom = y - h;
4889566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
489dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
490e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
491536b137fSBarry Smith   } else if (issaws) {
492d45a07a7SBarry Smith     PetscMPIInt rank;
4932657e9d9SBarry Smith     const char *name;
494d45a07a7SBarry Smith 
4959566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
4969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
497dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
498d45a07a7SBarry Smith       char dir[1024];
499d45a07a7SBarry Smith 
5009566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5019566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
502792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
50348a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5049566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
505792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
506f05ece33SBarry Smith     }
507bfb97211SBarry Smith #endif
50872a02f06SBarry Smith   }
50972a02f06SBarry Smith   if (snes->linesearch) {
5109566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5129566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
51419bcc07fSBarry Smith   }
515efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5179566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5194a0c5b0cSMatthew G Knepley   }
5209566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5219566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5229566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5239566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5242c155ee1SBarry Smith   if (snes->usesksp) {
5259566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5279566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5292c155ee1SBarry Smith   }
53072a02f06SBarry Smith   if (isdraw) {
53172a02f06SBarry Smith     PetscDraw draw;
5329566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5339566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5347f1410a3SPeter Brune   }
5353a40ed3dSBarry Smith   PetscFunctionReturn(0);
5369b94acceSBarry Smith }
5379b94acceSBarry Smith 
53876b2cf59SMatthew Knepley /*
53976b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
54076b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
54176b2cf59SMatthew Knepley */
54276b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
543a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5446849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
54576b2cf59SMatthew Knepley 
546ac226902SBarry Smith /*@C
547f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
54876b2cf59SMatthew Knepley 
54976b2cf59SMatthew Knepley   Not Collective
55076b2cf59SMatthew Knepley 
55176b2cf59SMatthew Knepley   Input Parameter:
55276b2cf59SMatthew Knepley . snescheck - function that checks for options
55376b2cf59SMatthew Knepley 
55476b2cf59SMatthew Knepley   Level: developer
55576b2cf59SMatthew Knepley 
556f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetFromOptions()`
55776b2cf59SMatthew Knepley @*/
558d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES))
559d71ae5a4SJacob Faibussowitsch {
56076b2cf59SMatthew Knepley   PetscFunctionBegin;
56163a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
56276b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
56376b2cf59SMatthew Knepley   PetscFunctionReturn(0);
56476b2cf59SMatthew Knepley }
56576b2cf59SMatthew Knepley 
566d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
567d71ae5a4SJacob Faibussowitsch {
568aa3661deSLisandro Dalcin   Mat          J;
569895c21f2SBarry Smith   MatNullSpace nullsp;
570aa3661deSLisandro Dalcin 
571aa3661deSLisandro Dalcin   PetscFunctionBegin;
5720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
573aa3661deSLisandro Dalcin 
57498613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
57598613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5769566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
57798613b67SLisandro Dalcin   }
57898613b67SLisandro Dalcin 
579aa3661deSLisandro Dalcin   if (version == 1) {
5809566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5819566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5829566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5831e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
584aa3661deSLisandro Dalcin   } else if (version == 2) {
5855f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
586570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
587f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
588aa3661deSLisandro Dalcin #else
5892479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
590aa3661deSLisandro Dalcin #endif
5912479783cSJose E. Roman   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
592aa3661deSLisandro Dalcin 
593895c21f2SBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix free matrix */
594895c21f2SBarry Smith   if (snes->jacobian) {
5959566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
5961baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
597895c21f2SBarry Smith   }
598895c21f2SBarry Smith 
59963a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
600d3462f78SMatthew Knepley   if (hasOperator) {
601aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
602aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6039566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
604aa3661deSLisandro Dalcin   } else {
605aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
6063232da50SPeter Brune      provided preconditioner Jacobian with the default matrix free version. */
607b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6089566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
609172a4300SPeter Brune     } else {
610789d8953SBarry Smith       KSP       ksp;
611789d8953SBarry Smith       PC        pc;
612789d8953SBarry Smith       PetscBool match;
613789d8953SBarry Smith 
6149566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
615aa3661deSLisandro Dalcin       /* Force no preconditioner */
6169566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6179566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6182698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
619aa3661deSLisandro Dalcin       if (!match) {
6209566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6219566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
622aa3661deSLisandro Dalcin       }
623aa3661deSLisandro Dalcin     }
624789d8953SBarry Smith   }
6259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
626aa3661deSLisandro Dalcin   PetscFunctionReturn(0);
627aa3661deSLisandro Dalcin }
628aa3661deSLisandro Dalcin 
629d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
630d71ae5a4SJacob Faibussowitsch {
631dfe15315SJed Brown   SNES snes = (SNES)ctx;
6320298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
633dfe15315SJed Brown 
634dfe15315SJed Brown   PetscFunctionBegin;
63516ebb321SJed Brown   if (PetscLogPrintInfo) {
63616ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6379566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6389566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6399566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6409566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
64163a3b9bcSJacob 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));
64216ebb321SJed Brown   }
643dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
644dfe15315SJed Brown   else {
6459566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
646dfe15315SJed Brown     Xfine = Xfine_named;
647dfe15315SJed Brown   }
6489566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
649907f5c5aSLawrence Mitchell   if (Inject) {
6509566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
651907f5c5aSLawrence Mitchell   } else {
6529566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6539566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
654907f5c5aSLawrence Mitchell   }
6559566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6569566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
657dfe15315SJed Brown   PetscFunctionReturn(0);
658dfe15315SJed Brown }
659dfe15315SJed Brown 
660d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
661d71ae5a4SJacob Faibussowitsch {
66216ebb321SJed Brown   PetscFunctionBegin;
6639566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
66416ebb321SJed Brown   PetscFunctionReturn(0);
66516ebb321SJed Brown }
66616ebb321SJed Brown 
667a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
668a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
669d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
670d71ae5a4SJacob Faibussowitsch {
671caa4e7f2SJed Brown   SNES  snes = (SNES)ctx;
6720298fd71SBarry Smith   Vec   X, Xnamed = NULL;
673dfe15315SJed Brown   DM    dmsave;
6744e269d77SPeter Brune   void *ctxsave;
67525ce1634SJed Brown   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = NULL;
676caa4e7f2SJed Brown 
677caa4e7f2SJed Brown   PetscFunctionBegin;
678dfe15315SJed Brown   dmsave = snes->dm;
6799566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
680dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
6819371c9d4SSatish Balay   else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */ PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
682dfe15315SJed Brown     X = Xnamed;
6839566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
6844e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
68548a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
6864e269d77SPeter Brune   }
6874dde8bb0SMatthew G. Knepley   /* Make sure KSP DM has the Jacobian computation routine */
6884dde8bb0SMatthew G. Knepley   {
6894dde8bb0SMatthew G. Knepley     DMSNES sdm;
6904e269d77SPeter Brune 
6919566063dSJacob Faibussowitsch     PetscCall(DMGetDMSNES(snes->dm, &sdm));
69248a46eb9SPierre Jolivet     if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
6934dde8bb0SMatthew G. Knepley   }
6942b93b426SMatthew G. Knepley   /* Compute the operators */
6959566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
6962b93b426SMatthew G. Knepley   /* Put the previous context back */
69748a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
6984e269d77SPeter Brune 
6999566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
700dfe15315SJed Brown   snes->dm = dmsave;
701caa4e7f2SJed Brown   PetscFunctionReturn(0);
702caa4e7f2SJed Brown }
703caa4e7f2SJed Brown 
7046cab3a1bSJed Brown /*@
705f6dfbefdSBarry Smith    SNESSetUpMatrices - ensures that matrices are available for `SNES`, this is called by `SNESSetUp_XXX()`
7066cab3a1bSJed Brown 
7076cab3a1bSJed Brown    Collective
7086cab3a1bSJed Brown 
7094165533cSJose E. Roman    Input Parameter:
7106cab3a1bSJed Brown .  snes - snes to configure
7116cab3a1bSJed Brown 
7126cab3a1bSJed Brown    Level: developer
7136cab3a1bSJed Brown 
714f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetUp()`
7156cab3a1bSJed Brown @*/
716d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
717d71ae5a4SJacob Faibussowitsch {
7186cab3a1bSJed Brown   DM     dm;
719942e3340SBarry Smith   DMSNES sdm;
7206cab3a1bSJed Brown 
7216cab3a1bSJed Brown   PetscFunctionBegin;
7229566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7239566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
72458b371f3SBarry Smith   if (!snes->jacobian && snes->mf) {
7256cab3a1bSJed Brown     Mat   J;
7266cab3a1bSJed Brown     void *functx;
7279566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7289566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7299566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7309566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7319566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7329566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
733caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7346cab3a1bSJed Brown     Mat J, B;
7359566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7369566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7379566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7389566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
73906f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7409566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7419566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
743caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7441ba9b98eSMatthew G. Knepley     PetscDS   prob;
7456cab3a1bSJed Brown     Mat       J, B;
7461ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7471ba9b98eSMatthew G. Knepley 
7486cab3a1bSJed Brown     J = snes->jacobian;
7499566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7509566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7519566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7529566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7539566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7549566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7559566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7569566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7576cab3a1bSJed Brown   }
758caa4e7f2SJed Brown   {
759caa4e7f2SJed Brown     KSP ksp;
7609566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
7619566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
7629566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
763caa4e7f2SJed Brown   }
7646cab3a1bSJed Brown   PetscFunctionReturn(0);
7656cab3a1bSJed Brown }
7666cab3a1bSJed Brown 
767d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
768d71ae5a4SJacob Faibussowitsch {
7695e7c47f3SMatthew G. Knepley   PetscInt i;
7705e7c47f3SMatthew G. Knepley 
7715e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
7725e7c47f3SMatthew G. Knepley   if (!snes->pauseFinal) PetscFunctionReturn(0);
7735e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
7745e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
7755e7c47f3SMatthew G. Knepley     PetscDraw             draw;
7765e7c47f3SMatthew G. Knepley     PetscReal             lpause;
7775e7c47f3SMatthew G. Knepley 
7785e7c47f3SMatthew G. Knepley     if (!vf) continue;
7795e7c47f3SMatthew G. Knepley     if (vf->lg) {
7805e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
7815e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
7829566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
7839566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
7849566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
7859566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
7869566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
7875e7c47f3SMatthew G. Knepley     } else {
7885e7c47f3SMatthew G. Knepley       PetscBool isdraw;
7895e7c47f3SMatthew G. Knepley 
7905e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
7915e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
7929566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
7935e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
7949566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &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     }
8005e7c47f3SMatthew G. Knepley   }
8015e7c47f3SMatthew G. Knepley   PetscFunctionReturn(0);
8025e7c47f3SMatthew G. Knepley }
8035e7c47f3SMatthew G. Knepley 
804fde5950dSBarry Smith /*@C
805fde5950dSBarry Smith    SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
806fde5950dSBarry Smith 
807c3339decSBarry Smith    Collective
808fde5950dSBarry Smith 
809fde5950dSBarry Smith    Input Parameters:
810fde5950dSBarry Smith +  snes - SNES object you wish to monitor
811fde5950dSBarry Smith .  name - the monitor type one is seeking
812fde5950dSBarry Smith .  help - message indicating what monitoring is done
813fde5950dSBarry Smith .  manual - manual page for the monitor
814fde5950dSBarry Smith .  monitor - the monitor function
815f6dfbefdSBarry 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
816fde5950dSBarry Smith 
817f6dfbefdSBarry Smith    Options Database Key:
818f6dfbefdSBarry Smith .  -name - trigger the use of this monitor in `SNESSetFromOptions()`
819f6dfbefdSBarry Smith 
820f6dfbefdSBarry Smith    Level: advanced
821fde5950dSBarry Smith 
822db781477SPatrick Sanan .seealso: `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
823db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
824db781477SPatrick Sanan           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
825db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
826c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
827db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
828db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
829fde5950dSBarry Smith @*/
830d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSetFromOptions(SNES snes, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNES, PetscInt, PetscReal, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(SNES, PetscViewerAndFormat *))
831d71ae5a4SJacob Faibussowitsch {
832fde5950dSBarry Smith   PetscViewer       viewer;
833fde5950dSBarry Smith   PetscViewerFormat format;
834fde5950dSBarry Smith   PetscBool         flg;
835fde5950dSBarry Smith 
836fde5950dSBarry Smith   PetscFunctionBegin;
8379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
838fde5950dSBarry Smith   if (flg) {
839d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8409566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
8419566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
8421baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8439566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
844fde5950dSBarry Smith   }
845fde5950dSBarry Smith   PetscFunctionReturn(0);
846fde5950dSBarry Smith }
847fde5950dSBarry Smith 
848d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, MPI_Comm comm, const char *prefix)
849d71ae5a4SJacob Faibussowitsch {
8500f0abf79SStefano Zampini   PetscFunctionBegin;
8510f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
8520f0abf79SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", NULL, kctx->version, &kctx->version, NULL));
8530f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", NULL, kctx->rtol_0, &kctx->rtol_0, NULL));
8540f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", NULL, kctx->rtol_max, &kctx->rtol_max, NULL));
8550f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", NULL, kctx->gamma, &kctx->gamma, NULL));
8560f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", NULL, kctx->alpha, &kctx->alpha, NULL));
8570f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
8580f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", NULL, kctx->threshold, &kctx->threshold, NULL));
8590f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8600f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8610f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8620f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8630f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8640f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8650f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8660f0abf79SStefano Zampini   PetscOptionsEnd();
8670f0abf79SStefano Zampini   PetscFunctionReturn(0);
8680f0abf79SStefano Zampini }
8690f0abf79SStefano Zampini 
8709b94acceSBarry Smith /*@
871f6dfbefdSBarry Smith    SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
8729b94acceSBarry Smith 
873c3339decSBarry Smith    Collective
874c7afd0dbSLois Curfman McInnes 
8759b94acceSBarry Smith    Input Parameter:
876f6dfbefdSBarry Smith .  snes - the `SNES` context
8779b94acceSBarry Smith 
87836851e7fSLois Curfman McInnes    Options Database Keys:
879f6dfbefdSBarry Smith +  -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
88082738288SBarry Smith .  -snes_stol - convergence tolerance in terms of the norm
88182738288SBarry Smith                 of the change in the solution between steps
88270441072SBarry Smith .  -snes_atol <abstol> - absolute tolerance of residual norm
883b39c3a46SLois Curfman McInnes .  -snes_rtol <rtol> - relative decrease in tolerance norm from initial
884e4d06f11SPatrick Farrell .  -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
885be5caee7SBarry Smith .  -snes_force_iteration <force> - force SNESSolve() to take at least one iteration
886b39c3a46SLois Curfman McInnes .  -snes_max_it <max_it> - maximum number of iterations
887b39c3a46SLois Curfman McInnes .  -snes_max_funcs <max_funcs> - maximum number of function evaluations
8884839bfe8SBarry Smith .  -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
889ddf469c8SBarry Smith .  -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
890a8054027SBarry Smith .  -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild)
8913d5a8a6aSBarry Smith .  -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve()
892e35cf81dSBarry Smith .  -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild)
8933d5a8a6aSBarry Smith .  -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve()
894b39c3a46SLois Curfman McInnes .  -snes_trtol <trtol> - trust region tolerance
895f362779dSJed Brown .  -snes_convergence_test - <default,skip,correct_pressure> convergence test in nonlinear solver.
896f6dfbefdSBarry Smith                                default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense
897f6dfbefdSBarry Smith                                of convergence test. correct_pressure S`NESConvergedCorrectPressure()` has special handling of a pressure null space.
898fde5950dSBarry Smith .  -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout
899fde5950dSBarry Smith .  -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
900fde5950dSBarry Smith .  -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration
901fde5950dSBarry Smith .  -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9024619e776SBarry Smith .  -snes_monitor_lg_residualnorm - plots residual norm at each iteration
903459f5d12SBarry Smith .  -snes_monitor_lg_range - plots residual norm at each iteration
9045e7c47f3SMatthew G. Knepley .  -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends
905e24b481bSBarry Smith .  -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
906e2e60de9SPeter Brune .  -snes_fd_color - use finite differences with coloring to compute Jacobian
9075968eb51SBarry Smith .  -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration
908b5badacbSBarry Smith .  -snes_converged_reason - print the reason for convergence/divergence after each solve
909e62ac41dSBarry Smith .  -npc_snes_type <type> - the SNES type to use as a nonlinear preconditioner
910e62ac41dSBarry 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.
911e62ac41dSBarry 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.
91282738288SBarry Smith 
913f6dfbefdSBarry Smith     Options Database Keys for Eisenstat-Walker method:
914fa9f3622SBarry Smith +  -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
9154b27c08aSLois Curfman McInnes .  -snes_ksp_ew_version ver - version of  Eisenstat-Walker method
91636851e7fSLois Curfman McInnes .  -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
91736851e7fSLois Curfman McInnes .  -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
91836851e7fSLois Curfman McInnes .  -snes_ksp_ew_gamma <gamma> - Sets gamma
91936851e7fSLois Curfman McInnes .  -snes_ksp_ew_alpha <alpha> - Sets alpha
92036851e7fSLois Curfman McInnes .  -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
92136851e7fSLois Curfman McInnes -  -snes_ksp_ew_threshold <threshold> - Sets threshold
92282738288SBarry Smith 
92311ca99fdSLois Curfman McInnes    Notes:
924ec5066bdSBarry Smith    To see all options, run your program with the -help option or consult the users manual
925ec5066bdSBarry Smith 
926f6dfbefdSBarry Smith    `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix free, and computing explicitly with
927f6dfbefdSBarry Smith    finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
92883e2fdc7SBarry Smith 
92936851e7fSLois Curfman McInnes    Level: beginner
93036851e7fSLois Curfman McInnes 
931f6dfbefdSBarry Smith .seealso: `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`
9329b94acceSBarry Smith @*/
933d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
934d71ae5a4SJacob Faibussowitsch {
9358afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
936d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
93704d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
938649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
93985385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9400f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
941c40d0f55SPeter Brune   PCSide      pcside;
942a64e098fSPeter Brune   const char *optionsprefix;
9439b94acceSBarry Smith 
9443a40ed3dSBarry Smith   PetscFunctionBegin;
9450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9469566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
947d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
948639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
950d64ed03dSBarry Smith   if (flg) {
9519566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9527adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9539566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
954d64ed03dSBarry Smith   }
9559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
9569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
957186905e3SBarry Smith 
9589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
9599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
9609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
9619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
9629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
9639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
9649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
9659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
9669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
96785385478SLisandro Dalcin 
9689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
969a8054027SBarry Smith   if (flg) {
9705f80ce2aSJacob 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");
9719566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
972a8054027SBarry Smith   }
9739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
9741baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
9759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
976e35cf81dSBarry Smith   if (flg) {
9775f80ce2aSJacob 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");
9789566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
979e35cf81dSBarry Smith   }
9809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
9811baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
98237ec4e1aSPeter Brune 
9839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
9841baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
985a8054027SBarry Smith 
9869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, sizeof(convtests) / sizeof(char *), "default", &indx, &flg));
98785385478SLisandro Dalcin   if (flg) {
98885385478SLisandro Dalcin     switch (indx) {
989d71ae5a4SJacob Faibussowitsch     case 0:
990d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
991d71ae5a4SJacob Faibussowitsch       break;
992d71ae5a4SJacob Faibussowitsch     case 1:
993d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
994d71ae5a4SJacob Faibussowitsch       break;
995d71ae5a4SJacob Faibussowitsch     case 2:
996d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
997d71ae5a4SJacob Faibussowitsch       break;
99885385478SLisandro Dalcin     }
99985385478SLisandro Dalcin   }
100085385478SLisandro Dalcin 
10019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10029566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1003fdacfa88SPeter Brune 
10049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10059566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1006186905e3SBarry Smith 
100785385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
100885385478SLisandro Dalcin 
10099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1010186905e3SBarry Smith 
10110f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10120f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
10130f0abf79SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PetscObjectComm((PetscObject)snes), ewprefix));
10140f0abf79SStefano Zampini 
10159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_ksp_ew_version", "Version 1, 2 or 3", "SNESKSPSetParametersEW", kctx->version, &kctx->version, NULL));
10169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_rtol0", "0 <= rtol0 < 1", "SNESKSPSetParametersEW", kctx->rtol_0, &kctx->rtol_0, NULL));
10179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_rtolmax", "0 <= rtolmax < 1", "SNESKSPSetParametersEW", kctx->rtol_max, &kctx->rtol_max, NULL));
10189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_gamma", "0 <= gamma <= 1", "SNESKSPSetParametersEW", kctx->gamma, &kctx->gamma, NULL));
10199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_alpha", "1 < alpha <= 2", "SNESKSPSetParametersEW", kctx->alpha, &kctx->alpha, NULL));
10209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_alpha2", "alpha2", "SNESKSPSetParametersEW", kctx->alpha2, &kctx->alpha2, NULL));
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_threshold", "0 < threshold < 1", "SNESKSPSetParametersEW", kctx->threshold, &kctx->threshold, NULL));
1022186905e3SBarry Smith 
102390d69ab7SBarry Smith   flg = PETSC_FALSE;
10249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10259566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1026eabae89aSBarry Smith 
10279566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10289566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10299566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1030eabae89aSBarry Smith 
10319566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10329566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10339566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10349566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10359566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10369566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10379566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10392db13446SMatthew G. Knepley 
10409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10419566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10425180491cSLisandro Dalcin 
104390d69ab7SBarry Smith   flg = PETSC_FALSE;
10449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1045459f5d12SBarry Smith   if (flg) {
1046459f5d12SBarry Smith     PetscViewer ctx;
1047e24b481bSBarry Smith 
10489566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10499566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1050459f5d12SBarry Smith   }
10512e7541e6SPeter Brune 
105290d69ab7SBarry Smith   flg = PETSC_FALSE;
10539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10549566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1055c4421ceaSFande Kong 
1056c4421ceaSFande Kong   flg = PETSC_FALSE;
10579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10584b27c08aSLois Curfman McInnes   if (flg) {
10596cab3a1bSJed Brown     void *functx;
1060b1f624c7SBarry Smith     DM    dm;
10619566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1062800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10639566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10649566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10659566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
10669b94acceSBarry Smith   }
1067639f9d9dSBarry Smith 
106844848bc4SPeter Brune   flg = PETSC_FALSE;
10699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
10701baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
107197584545SPeter Brune 
107297584545SPeter Brune   flg = PETSC_FALSE;
10739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
107444848bc4SPeter Brune   if (flg) {
1075c52e227fSPeter Brune     DM dm;
10769566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1077800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10789566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
10799566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
108044848bc4SPeter Brune   }
108144848bc4SPeter Brune 
1082aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1084d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1085a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1086d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1087a8248277SBarry Smith   }
1088aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1090d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
10919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1092d28543b3SPeter Brune 
1093c40d0f55SPeter Brune   flg = PETSC_FALSE;
10949566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
10959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
10969566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1097c40d0f55SPeter Brune 
1098e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
10998a70d858SHong Zhang   /*
11008a70d858SHong Zhang     Publish convergence information using SAWs
11018a70d858SHong Zhang   */
11028a70d858SHong Zhang   flg = PETSC_FALSE;
11039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11048a70d858SHong Zhang   if (flg) {
11058a70d858SHong Zhang     void *ctx;
11069566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11079566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11088a70d858SHong Zhang   }
11098a70d858SHong Zhang #endif
11108a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1111b90c6cbeSBarry Smith   {
1112b90c6cbeSBarry Smith     PetscBool set;
1113b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11149566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11151baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1116b90c6cbeSBarry Smith   }
1117b90c6cbeSBarry Smith #endif
1118b90c6cbeSBarry Smith 
111948a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
112076b2cf59SMatthew Knepley 
1121dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11225d973c19SBarry Smith 
11235d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1124dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1125d0609cedSBarry Smith   PetscOptionsEnd();
11264bbc92c1SBarry Smith 
1127d8d34be6SBarry Smith   if (snes->linesearch) {
11289566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11299566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1130d8d34be6SBarry Smith   }
11319e764e56SPeter Brune 
11326aa5e7e9SBarry Smith   if (snes->usesksp) {
11339566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11349566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11359566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11366aa5e7e9SBarry Smith   }
11376991f827SBarry Smith 
1138b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11399566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
114148a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11421baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1143b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
1144b3cd9a81SMatthew G. Knepley   PetscFunctionReturn(0);
1145b3cd9a81SMatthew G. Knepley }
1146b3cd9a81SMatthew G. Knepley 
1147b3cd9a81SMatthew G. Knepley /*@
1148f6dfbefdSBarry Smith    SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously set from options
1149b3cd9a81SMatthew G. Knepley 
1150c3339decSBarry Smith    Collective
1151b3cd9a81SMatthew G. Knepley 
1152b3cd9a81SMatthew G. Knepley    Input Parameter:
1153f6dfbefdSBarry Smith .  snes - the `SNES` context
1154b3cd9a81SMatthew G. Knepley 
1155b3cd9a81SMatthew G. Knepley    Level: beginner
1156b3cd9a81SMatthew G. Knepley 
1157f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1158b3cd9a81SMatthew G. Knepley @*/
1159d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1160d71ae5a4SJacob Faibussowitsch {
1161b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11629566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11633a40ed3dSBarry Smith   PetscFunctionReturn(0);
11649b94acceSBarry Smith }
11659b94acceSBarry Smith 
1166bb9467b5SJed Brown /*@C
1167d25893d9SBarry Smith    SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1168d25893d9SBarry Smith    the nonlinear solvers.
1169d25893d9SBarry Smith 
1170c3339decSBarry Smith    Logically Collective
1171d25893d9SBarry Smith 
1172d25893d9SBarry Smith    Input Parameters:
1173f6dfbefdSBarry Smith +  snes - the `SNES` context
1174d25893d9SBarry Smith .  compute - function to compute the context
1175d25893d9SBarry Smith -  destroy - function to destroy the context
1176d25893d9SBarry Smith 
1177d25893d9SBarry Smith    Level: intermediate
1178d25893d9SBarry Smith 
1179f6dfbefdSBarry Smith    Note:
1180f6dfbefdSBarry Smith    This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1181f6dfbefdSBarry Smith 
1182f6dfbefdSBarry Smith    Use `SNESSetApplicationContext()` to see the context immediately
1183f6dfbefdSBarry Smith 
1184f6dfbefdSBarry Smith    Fortran Note:
1185bb9467b5SJed Brown    This function is currently not available from Fortran.
1186bb9467b5SJed Brown 
1187f6dfbefdSBarry Smith .seealso: `SNESGetApplicationContext()`, `SNESSetComputeApplicationContext()`, `SNESSetApplicationContext()`
1188d25893d9SBarry Smith @*/
1189d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES, void **), PetscErrorCode (*destroy)(void **))
1190d71ae5a4SJacob Faibussowitsch {
1191d25893d9SBarry Smith   PetscFunctionBegin;
1192d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1193d25893d9SBarry Smith   snes->ops->usercompute = compute;
1194d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
1195d25893d9SBarry Smith   PetscFunctionReturn(0);
1196d25893d9SBarry Smith }
1197a847f771SSatish Balay 
1198b07ff414SBarry Smith /*@
1199f6dfbefdSBarry Smith    SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12009b94acceSBarry Smith 
1201c3339decSBarry Smith    Logically Collective
1202fee21e36SBarry Smith 
1203c7afd0dbSLois Curfman McInnes    Input Parameters:
1204f6dfbefdSBarry Smith +  snes - the `SNES` context
1205c7afd0dbSLois Curfman McInnes -  usrP - optional user context
1206c7afd0dbSLois Curfman McInnes 
120736851e7fSLois Curfman McInnes    Level: intermediate
120836851e7fSLois Curfman McInnes 
1209f6dfbefdSBarry Smith    Notes:
1210f6dfbefdSBarry Smith    Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1211f6dfbefdSBarry Smith    with `SNESGetApplicationContext()`
1212f6dfbefdSBarry Smith 
1213f6dfbefdSBarry Smith    To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1214f6dfbefdSBarry Smith 
1215f6dfbefdSBarry Smith    Fortran Note:
121695452b02SPatrick Sanan     To use this from Fortran you must write a Fortran interface definition for this
1217daf670e6SBarry Smith     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1218daf670e6SBarry Smith 
1219f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12209b94acceSBarry Smith @*/
1221d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1222d71ae5a4SJacob Faibussowitsch {
1223b07ff414SBarry Smith   KSP ksp;
12241b2093e4SBarry Smith 
12253a40ed3dSBarry Smith   PetscFunctionBegin;
12260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12279566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12289566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12299b94acceSBarry Smith   snes->user = usrP;
12303a40ed3dSBarry Smith   PetscFunctionReturn(0);
12319b94acceSBarry Smith }
123274679c65SBarry Smith 
1233b07ff414SBarry Smith /*@
12349b94acceSBarry Smith    SNESGetApplicationContext - Gets the user-defined context for the
1235f6dfbefdSBarry Smith    nonlinear solvers set with `SNESGetApplicationContext()` or with `SNESSetComputeApplicationContext()`
12369b94acceSBarry Smith 
1237c7afd0dbSLois Curfman McInnes    Not Collective
1238c7afd0dbSLois Curfman McInnes 
12399b94acceSBarry Smith    Input Parameter:
1240f6dfbefdSBarry Smith .  snes - `SNES` context
12419b94acceSBarry Smith 
12429b94acceSBarry Smith    Output Parameter:
12439b94acceSBarry Smith .  usrP - user context
12449b94acceSBarry Smith 
1245f6dfbefdSBarry Smith    Fortran Note:
124695452b02SPatrick Sanan     To use this from Fortran you must write a Fortran interface definition for this
1247daf670e6SBarry Smith     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1248daf670e6SBarry Smith 
124936851e7fSLois Curfman McInnes    Level: intermediate
125036851e7fSLois Curfman McInnes 
1251db781477SPatrick Sanan .seealso: `SNESSetApplicationContext()`
12529b94acceSBarry Smith @*/
1253d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1254d71ae5a4SJacob Faibussowitsch {
12553a40ed3dSBarry Smith   PetscFunctionBegin;
12560700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1257e71120c6SJed Brown   *(void **)usrP = snes->user;
12583a40ed3dSBarry Smith   PetscFunctionReturn(0);
12599b94acceSBarry Smith }
126074679c65SBarry Smith 
12619b94acceSBarry Smith /*@
1262f6dfbefdSBarry Smith    SNESSetUseMatrixFree - indicates that `SNES` should use matrix free finite difference matrix vector products to apply the Jacobian.
12633565c898SBarry Smith 
1264f6dfbefdSBarry Smith    Logically Collective on snes, the values must be the same on all MPI ranks
12653565c898SBarry Smith 
12663565c898SBarry Smith    Input Parameters:
1267f6dfbefdSBarry Smith +  snes - `SNES` context
1268f6dfbefdSBarry Smith .  mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1269f6dfbefdSBarry 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
1270f6dfbefdSBarry Smith    this option no matrix element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
12713565c898SBarry Smith 
1272f6dfbefdSBarry Smith    Options Database Keys:
1273f6dfbefdSBarry Smith + -snes_mf_operator - use matrix free only for the mat operator
1274f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator
1275ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences.
1276ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow)
12773565c898SBarry Smith 
12783565c898SBarry Smith    Level: intermediate
12793565c898SBarry Smith 
1280f6dfbefdSBarry Smith    Note:
1281f6dfbefdSBarry Smith    SNES supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free, and computing explicitly with
1282f6dfbefdSBarry Smith    finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1283ec5066bdSBarry Smith 
1284f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`
12853565c898SBarry Smith @*/
1286d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1287d71ae5a4SJacob Faibussowitsch {
12883565c898SBarry Smith   PetscFunctionBegin;
12893565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
129088b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
129188b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
12924ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
12933565c898SBarry Smith   snes->mf_operator = mf_operator;
12943565c898SBarry Smith   PetscFunctionReturn(0);
12953565c898SBarry Smith }
12963565c898SBarry Smith 
12973565c898SBarry Smith /*@
1298f6dfbefdSBarry Smith    SNESGetUseMatrixFree - indicates if the SNES uses matrix-free finite difference matrix vector products to apply the Jacobian.
12993565c898SBarry Smith 
1300f6dfbefdSBarry Smith    Not Collective, but the resulting flags will be the same on all MPI ranks
13013565c898SBarry Smith 
13023565c898SBarry Smith    Input Parameter:
1303f6dfbefdSBarry Smith .  snes - `SNES` context
13043565c898SBarry Smith 
13053565c898SBarry Smith    Output Parameters:
1306f6dfbefdSBarry Smith +  mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1307f6dfbefdSBarry 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
13083565c898SBarry Smith 
13093565c898SBarry Smith    Level: intermediate
13103565c898SBarry Smith 
1311f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13123565c898SBarry Smith @*/
1313d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1314d71ae5a4SJacob Faibussowitsch {
13153565c898SBarry Smith   PetscFunctionBegin;
13163565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13173565c898SBarry Smith   if (mf) *mf = snes->mf;
13183565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13193565c898SBarry Smith   PetscFunctionReturn(0);
13203565c898SBarry Smith }
13213565c898SBarry Smith 
13223565c898SBarry Smith /*@
1323c8228a4eSBarry Smith    SNESGetIterationNumber - Gets the number of nonlinear iterations completed
1324c8228a4eSBarry Smith    at this time.
13259b94acceSBarry Smith 
1326c7afd0dbSLois Curfman McInnes    Not Collective
1327c7afd0dbSLois Curfman McInnes 
13289b94acceSBarry Smith    Input Parameter:
1329f6dfbefdSBarry Smith .  snes - `SNES` context
13309b94acceSBarry Smith 
13319b94acceSBarry Smith    Output Parameter:
13329b94acceSBarry Smith .  iter - iteration number
13339b94acceSBarry Smith 
1334c8228a4eSBarry Smith    Notes:
1335c8228a4eSBarry Smith    For example, during the computation of iteration 2 this would return 1.
1336c8228a4eSBarry Smith 
1337c8228a4eSBarry Smith    This is useful for using lagged Jacobians (where one does not recompute the
1338f6dfbefdSBarry Smith    Jacobian at each `SNES` iteration). For example, the code
133908405cd6SLois Curfman McInnes .vb
134008405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
134108405cd6SLois Curfman McInnes       if (!(it % 2)) {
134208405cd6SLois Curfman McInnes         [compute Jacobian here]
134308405cd6SLois Curfman McInnes       }
134408405cd6SLois Curfman McInnes .ve
1345f6dfbefdSBarry Smith    can be used in your function that computes the Jacobian to cause the Jacobian to be
1346f6dfbefdSBarry Smith    recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1347c8228a4eSBarry Smith 
1348f6dfbefdSBarry Smith    After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1349c04deec6SBarry Smith 
135036851e7fSLois Curfman McInnes    Level: intermediate
135136851e7fSLois Curfman McInnes 
1352f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`
13539b94acceSBarry Smith @*/
1354d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1355d71ae5a4SJacob Faibussowitsch {
13563a40ed3dSBarry Smith   PetscFunctionBegin;
13570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13584482741eSBarry Smith   PetscValidIntPointer(iter, 2);
13599b94acceSBarry Smith   *iter = snes->iter;
13603a40ed3dSBarry Smith   PetscFunctionReturn(0);
13619b94acceSBarry Smith }
136274679c65SBarry Smith 
1363360c497dSPeter Brune /*@
1364360c497dSPeter Brune    SNESSetIterationNumber - Sets the current iteration number.
1365360c497dSPeter Brune 
1366360c497dSPeter Brune    Not Collective
1367360c497dSPeter Brune 
1368d8d19677SJose E. Roman    Input Parameters:
1369f6dfbefdSBarry Smith +  snes - `SNES` context
1370a2b725a8SWilliam Gropp -  iter - iteration number
1371360c497dSPeter Brune 
1372360c497dSPeter Brune    Level: developer
1373360c497dSPeter Brune 
1374db781477SPatrick Sanan .seealso: `SNESGetLinearSolveIterations()`
1375360c497dSPeter Brune @*/
1376d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1377d71ae5a4SJacob Faibussowitsch {
1378360c497dSPeter Brune   PetscFunctionBegin;
1379360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13809566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1381360c497dSPeter Brune   snes->iter = iter;
13829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
1383360c497dSPeter Brune   PetscFunctionReturn(0);
1384360c497dSPeter Brune }
1385360c497dSPeter Brune 
13869b94acceSBarry Smith /*@
1387b850b91aSLisandro Dalcin    SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
13889b94acceSBarry Smith    attempted by the nonlinear solver.
13899b94acceSBarry Smith 
1390c7afd0dbSLois Curfman McInnes    Not Collective
1391c7afd0dbSLois Curfman McInnes 
13929b94acceSBarry Smith    Input Parameter:
1393f6dfbefdSBarry Smith .  snes - `SNES` context
13949b94acceSBarry Smith 
13959b94acceSBarry Smith    Output Parameter:
13969b94acceSBarry Smith .  nfails - number of unsuccessful steps attempted
13979b94acceSBarry Smith 
1398f6dfbefdSBarry Smith    Note:
1399f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()`.
1400c96a6f78SLois Curfman McInnes 
140136851e7fSLois Curfman McInnes    Level: intermediate
140236851e7fSLois Curfman McInnes 
1403f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1404db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14059b94acceSBarry Smith @*/
1406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1407d71ae5a4SJacob Faibussowitsch {
14083a40ed3dSBarry Smith   PetscFunctionBegin;
14090700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14104482741eSBarry Smith   PetscValidIntPointer(nfails, 2);
141150ffb88aSMatthew Knepley   *nfails = snes->numFailures;
141250ffb88aSMatthew Knepley   PetscFunctionReturn(0);
141350ffb88aSMatthew Knepley }
141450ffb88aSMatthew Knepley 
141550ffb88aSMatthew Knepley /*@
1416b850b91aSLisandro Dalcin    SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1417f6dfbefdSBarry Smith    attempted by the nonlinear solver before it gives up and generates an error
141850ffb88aSMatthew Knepley 
141950ffb88aSMatthew Knepley    Not Collective
142050ffb88aSMatthew Knepley 
142150ffb88aSMatthew Knepley    Input Parameters:
1422f6dfbefdSBarry Smith +  snes     - `SNES` context
142350ffb88aSMatthew Knepley -  maxFails - maximum of unsuccessful steps
142450ffb88aSMatthew Knepley 
142550ffb88aSMatthew Knepley    Level: intermediate
142650ffb88aSMatthew Knepley 
1427f6dfbefdSBarry Smith .seealso: `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1428db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
142950ffb88aSMatthew Knepley @*/
1430d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1431d71ae5a4SJacob Faibussowitsch {
143250ffb88aSMatthew Knepley   PetscFunctionBegin;
14330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
143450ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
143550ffb88aSMatthew Knepley   PetscFunctionReturn(0);
143650ffb88aSMatthew Knepley }
143750ffb88aSMatthew Knepley 
143850ffb88aSMatthew Knepley /*@
1439b850b91aSLisandro Dalcin    SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1440f6dfbefdSBarry Smith    attempted by the nonlinear solver before it gives up and generates an error
144150ffb88aSMatthew Knepley 
144250ffb88aSMatthew Knepley    Not Collective
144350ffb88aSMatthew Knepley 
144450ffb88aSMatthew Knepley    Input Parameter:
144550ffb88aSMatthew Knepley .  snes     - SNES context
144650ffb88aSMatthew Knepley 
144750ffb88aSMatthew Knepley    Output Parameter:
144850ffb88aSMatthew Knepley .  maxFails - maximum of unsuccessful steps
144950ffb88aSMatthew Knepley 
145050ffb88aSMatthew Knepley    Level: intermediate
145150ffb88aSMatthew Knepley 
1452f6dfbefdSBarry Smith .seealso: `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1453db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
145450ffb88aSMatthew Knepley @*/
1455d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1456d71ae5a4SJacob Faibussowitsch {
145750ffb88aSMatthew Knepley   PetscFunctionBegin;
14580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14594482741eSBarry Smith   PetscValidIntPointer(maxFails, 2);
146050ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
14613a40ed3dSBarry Smith   PetscFunctionReturn(0);
14629b94acceSBarry Smith }
1463a847f771SSatish Balay 
14642541af92SBarry Smith /*@
14652541af92SBarry Smith    SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1466f6dfbefdSBarry Smith      done by the `SNES` object
14672541af92SBarry Smith 
14682541af92SBarry Smith    Not Collective
14692541af92SBarry Smith 
14702541af92SBarry Smith    Input Parameter:
1471f6dfbefdSBarry Smith .  snes     - `SNES` context
14722541af92SBarry Smith 
14732541af92SBarry Smith    Output Parameter:
14742541af92SBarry Smith .  nfuncs - number of evaluations
14752541af92SBarry Smith 
14762541af92SBarry Smith    Level: intermediate
14772541af92SBarry Smith 
1478f6dfbefdSBarry Smith    Note:
1479f6dfbefdSBarry Smith     Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1480971e163fSPeter Brune 
1481f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
14822541af92SBarry Smith @*/
1483d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1484d71ae5a4SJacob Faibussowitsch {
14852541af92SBarry Smith   PetscFunctionBegin;
14860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14872541af92SBarry Smith   PetscValidIntPointer(nfuncs, 2);
14882541af92SBarry Smith   *nfuncs = snes->nfuncs;
14892541af92SBarry Smith   PetscFunctionReturn(0);
14902541af92SBarry Smith }
14912541af92SBarry Smith 
14923d4c4710SBarry Smith /*@
14933d4c4710SBarry Smith    SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
14943d4c4710SBarry Smith    linear solvers.
14953d4c4710SBarry Smith 
14963d4c4710SBarry Smith    Not Collective
14973d4c4710SBarry Smith 
14983d4c4710SBarry Smith    Input Parameter:
1499f6dfbefdSBarry Smith .  snes - `SNES` context
15003d4c4710SBarry Smith 
15013d4c4710SBarry Smith    Output Parameter:
15023d4c4710SBarry Smith .  nfails - number of failed solves
15033d4c4710SBarry Smith 
1504f6dfbefdSBarry Smith    Options Database Key:
15059d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15069d85da0cSMatthew G. Knepley 
1507f6dfbefdSBarry Smith    Level: intermediate
1508f6dfbefdSBarry Smith 
1509f6dfbefdSBarry Smith    Note:
1510f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()`.
15113d4c4710SBarry Smith 
1512db781477SPatrick Sanan .seealso: `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15133d4c4710SBarry Smith @*/
1514d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1515d71ae5a4SJacob Faibussowitsch {
15163d4c4710SBarry Smith   PetscFunctionBegin;
15170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15183d4c4710SBarry Smith   PetscValidIntPointer(nfails, 2);
15193d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15203d4c4710SBarry Smith   PetscFunctionReturn(0);
15213d4c4710SBarry Smith }
15223d4c4710SBarry Smith 
15233d4c4710SBarry Smith /*@
15243d4c4710SBarry Smith    SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1525f6dfbefdSBarry Smith    allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15263d4c4710SBarry Smith 
1527c3339decSBarry Smith    Logically Collective
15283d4c4710SBarry Smith 
15293d4c4710SBarry Smith    Input Parameters:
1530f6dfbefdSBarry Smith +  snes     - `SNES` context
15313d4c4710SBarry Smith -  maxFails - maximum allowed linear solve failures
15323d4c4710SBarry Smith 
15333d4c4710SBarry Smith    Level: intermediate
15343d4c4710SBarry Smith 
1535f6dfbefdSBarry Smith    Options Database Key:
15369d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15379d85da0cSMatthew G. Knepley 
1538f6dfbefdSBarry Smith    Note:
1539f6dfbefdSBarry Smith     By default this is 0; that is `SNES` returns on the first failed linear solve
15403d4c4710SBarry Smith 
1541f6dfbefdSBarry Smith .seealso: `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
15423d4c4710SBarry Smith @*/
1543d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1544d71ae5a4SJacob Faibussowitsch {
15453d4c4710SBarry Smith   PetscFunctionBegin;
15460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1547c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
15483d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
15493d4c4710SBarry Smith   PetscFunctionReturn(0);
15503d4c4710SBarry Smith }
15513d4c4710SBarry Smith 
15523d4c4710SBarry Smith /*@
15533d4c4710SBarry Smith    SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1554f6dfbefdSBarry Smith      are allowed before `SNES` returns as unsuccessful
15553d4c4710SBarry Smith 
15563d4c4710SBarry Smith    Not Collective
15573d4c4710SBarry Smith 
15583d4c4710SBarry Smith    Input Parameter:
1559f6dfbefdSBarry Smith .  snes     - `SNES` context
15603d4c4710SBarry Smith 
15613d4c4710SBarry Smith    Output Parameter:
15623d4c4710SBarry Smith .  maxFails - maximum of unsuccessful solves allowed
15633d4c4710SBarry Smith 
15643d4c4710SBarry Smith    Level: intermediate
15653d4c4710SBarry Smith 
1566f6dfbefdSBarry Smith    Note:
1567f6dfbefdSBarry Smith     By default this is 1; that is `SNES` returns on the first failed linear solve
15683d4c4710SBarry Smith 
1569f6dfbefdSBarry Smith .seealso: `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
15703d4c4710SBarry Smith @*/
1571d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1572d71ae5a4SJacob Faibussowitsch {
15733d4c4710SBarry Smith   PetscFunctionBegin;
15740700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15753d4c4710SBarry Smith   PetscValidIntPointer(maxFails, 2);
15763d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
15773d4c4710SBarry Smith   PetscFunctionReturn(0);
15783d4c4710SBarry Smith }
15793d4c4710SBarry Smith 
1580c96a6f78SLois Curfman McInnes /*@
1581b850b91aSLisandro Dalcin    SNESGetLinearSolveIterations - Gets the total number of linear iterations
1582c96a6f78SLois Curfman McInnes    used by the nonlinear solver.
1583c96a6f78SLois Curfman McInnes 
1584c7afd0dbSLois Curfman McInnes    Not Collective
1585c7afd0dbSLois Curfman McInnes 
1586c96a6f78SLois Curfman McInnes    Input Parameter:
1587f6dfbefdSBarry Smith .  snes - `SNES` context
1588c96a6f78SLois Curfman McInnes 
1589c96a6f78SLois Curfman McInnes    Output Parameter:
1590c96a6f78SLois Curfman McInnes .  lits - number of linear iterations
1591c96a6f78SLois Curfman McInnes 
1592c96a6f78SLois Curfman McInnes    Notes:
1593f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1594c96a6f78SLois Curfman McInnes 
1595f6dfbefdSBarry 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
1596f6dfbefdSBarry Smith    then call `KSPGetIterationNumber()` after the failed solve.
1597010be392SBarry Smith 
159836851e7fSLois Curfman McInnes    Level: intermediate
159936851e7fSLois Curfman McInnes 
1600f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1601c96a6f78SLois Curfman McInnes @*/
1602d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1603d71ae5a4SJacob Faibussowitsch {
16043a40ed3dSBarry Smith   PetscFunctionBegin;
16050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16064482741eSBarry Smith   PetscValidIntPointer(lits, 2);
1607c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16083a40ed3dSBarry Smith   PetscFunctionReturn(0);
1609c96a6f78SLois Curfman McInnes }
1610c96a6f78SLois Curfman McInnes 
1611971e163fSPeter Brune /*@
1612971e163fSPeter Brune    SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1613f6dfbefdSBarry Smith    are reset every time `SNESSolve()` is called.
1614971e163fSPeter Brune 
1615c3339decSBarry Smith    Logically Collective
1616971e163fSPeter Brune 
1617d8d19677SJose E. Roman    Input Parameters:
1618f6dfbefdSBarry Smith +  snes - `SNES` context
1619f6dfbefdSBarry Smith -  reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1620971e163fSPeter Brune 
1621971e163fSPeter Brune    Level: developer
1622971e163fSPeter Brune 
1623db781477SPatrick Sanan .seealso: `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1624971e163fSPeter Brune @*/
1625d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1626d71ae5a4SJacob Faibussowitsch {
1627971e163fSPeter Brune   PetscFunctionBegin;
1628971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1629971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1630971e163fSPeter Brune   snes->counters_reset = reset;
1631971e163fSPeter Brune   PetscFunctionReturn(0);
1632971e163fSPeter Brune }
1633971e163fSPeter Brune 
16342999313aSBarry Smith /*@
1635f6dfbefdSBarry Smith    SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16362999313aSBarry Smith 
1637f6dfbefdSBarry Smith    Not Collective, but the `SNES` and `KSP` objects must live on the same MPI_Comm
16382999313aSBarry Smith 
16392999313aSBarry Smith    Input Parameters:
1640f6dfbefdSBarry Smith +  snes - the `SNES` context
1641f6dfbefdSBarry Smith -  ksp - the `KSP` context
16422999313aSBarry Smith 
16432999313aSBarry Smith    Notes:
1644f6dfbefdSBarry Smith    The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
16452999313aSBarry Smith    so this routine is rarely needed.
16462999313aSBarry Smith 
1647f6dfbefdSBarry Smith    The `KSP` object that is already in the `SNES` object has its reference count
16482999313aSBarry Smith    decreased by one.
16492999313aSBarry Smith 
16502999313aSBarry Smith    Level: developer
16512999313aSBarry Smith 
1652f6dfbefdSBarry Smith .seealso: `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
16532999313aSBarry Smith @*/
1654d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1655d71ae5a4SJacob Faibussowitsch {
16562999313aSBarry Smith   PetscFunctionBegin;
16570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16580700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
16592999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
16609566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
16619566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
16622999313aSBarry Smith   snes->ksp = ksp;
16632999313aSBarry Smith   PetscFunctionReturn(0);
16642999313aSBarry Smith }
16652999313aSBarry Smith 
166652baeb72SSatish Balay /*@
16679b94acceSBarry Smith    SNESCreate - Creates a nonlinear solver context.
16689b94acceSBarry Smith 
1669d083f849SBarry Smith    Collective
1670c7afd0dbSLois Curfman McInnes 
1671f6dfbefdSBarry Smith    Input Parameter:
1672906ed7ccSBarry Smith .  comm - MPI communicator
16739b94acceSBarry Smith 
16749b94acceSBarry Smith    Output Parameter:
16759b94acceSBarry Smith .  outsnes - the new SNES context
16769b94acceSBarry Smith 
1677c7afd0dbSLois Curfman McInnes    Options Database Keys:
1678c7afd0dbSLois Curfman McInnes +   -snes_mf - Activates default matrix-free Jacobian-vector products,
1679c7afd0dbSLois Curfman McInnes                and no preconditioning matrix
1680c7afd0dbSLois Curfman McInnes .   -snes_mf_operator - Activates default matrix-free Jacobian-vector
1681c7afd0dbSLois Curfman McInnes                products, and a user-provided preconditioning matrix
1682c7afd0dbSLois Curfman McInnes                as set by SNESSetJacobian()
1683c7afd0dbSLois Curfman McInnes -   -snes_fd - Uses (slow!) finite differences to compute Jacobian
1684c1f60f51SBarry Smith 
168536851e7fSLois Curfman McInnes    Level: beginner
168636851e7fSLois Curfman McInnes 
168795452b02SPatrick Sanan    Developer Notes:
1688f6dfbefdSBarry Smith    `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1689efd4aadfSBarry Smith    unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1690f6dfbefdSBarry Smith    particular method does use `KSP` and regulates if the information about the `KSP` is printed
1691f6dfbefdSBarry Smith    in `SNESView()`.
1692efd4aadfSBarry Smith 
1693f6dfbefdSBarry Smith    `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1694f6dfbefdSBarry Smith    by help messages about meaningless `SNES` options.
1695f6dfbefdSBarry Smith 
1696f6dfbefdSBarry Smith    `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should
1697efd4aadfSBarry Smith                     be fixed.
1698efd4aadfSBarry Smith 
1699f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
17009b94acceSBarry Smith @*/
1701d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1702d71ae5a4SJacob Faibussowitsch {
17039b94acceSBarry Smith   SNES       snes;
1704fa9f3622SBarry Smith   SNESKSPEW *kctx;
170537fcc0dbSBarry Smith 
17063a40ed3dSBarry Smith   PetscFunctionBegin;
1707ed1caa07SMatthew Knepley   PetscValidPointer(outsnes, 2);
17080298fd71SBarry Smith   *outsnes = NULL;
17099566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17108ba1e511SMatthew Knepley 
17119566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17127adad957SLisandro Dalcin 
17138d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
17142c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
171588976e71SPeter Brune   snes->tolerancesset  = PETSC_FALSE;
17169b94acceSBarry Smith   snes->max_its        = 50;
17179750a799SBarry Smith   snes->max_funcs      = 10000;
17189b94acceSBarry Smith   snes->norm           = 0.0;
1719c1e67a49SFande Kong   snes->xnorm          = 0.0;
1720c1e67a49SFande Kong   snes->ynorm          = 0.0;
1721365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
17226c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
17233a2046daSBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
17243a2046daSBarry Smith   snes->rtol = 1.e-5;
17253a2046daSBarry Smith #else
1726b4874afaSBarry Smith   snes->rtol = 1.e-8;
17273a2046daSBarry Smith #endif
1728b4874afaSBarry Smith   snes->ttol = 0.0;
17293a2046daSBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
17303a2046daSBarry Smith   snes->abstol = 1.e-25;
17313a2046daSBarry Smith #else
173270441072SBarry Smith   snes->abstol = 1.e-50;
17333a2046daSBarry Smith #endif
17347cd0ae37SLisandro Dalcin #if defined(PETSC_USE_REAL_SINGLE)
17357cd0ae37SLisandro Dalcin   snes->stol = 1.e-5;
17367cd0ae37SLisandro Dalcin #else
1737c60f73f4SPeter Brune   snes->stol = 1.e-8;
17387cd0ae37SLisandro Dalcin #endif
17393a2046daSBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
17403a2046daSBarry Smith   snes->deltatol = 1.e-6;
17413a2046daSBarry Smith #else
17424b27c08aSLois Curfman McInnes   snes->deltatol = 1.e-12;
17433a2046daSBarry Smith #endif
1744e37c518bSBarry Smith   snes->divtol               = 1.e4;
1745e37c518bSBarry Smith   snes->rnorm0               = 0;
17469b94acceSBarry Smith   snes->nfuncs               = 0;
174750ffb88aSMatthew Knepley   snes->numFailures          = 0;
174850ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17497a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1750e35cf81dSBarry Smith   snes->lagjacobian          = 1;
175137ec4e1aSPeter Brune   snes->jac_iter             = 0;
175237ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1753a8054027SBarry Smith   snes->lagpreconditioner    = 1;
175437ec4e1aSPeter Brune   snes->pre_iter             = 0;
175537ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1756639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1757c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17589e5d0892SLisandro Dalcin   snes->data                 = NULL;
17594dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1760186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17616f24a144SLois Curfman McInnes   snes->nwork                = 0;
17629e5d0892SLisandro Dalcin   snes->work                 = NULL;
176358c9b817SLisandro Dalcin   snes->nvwork               = 0;
17649e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1765758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1766758f92a0SBarry Smith   snes->conv_hist_max        = 0;
17670298fd71SBarry Smith   snes->conv_hist            = NULL;
17680298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1769758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1770971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1771e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1772184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1773efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1774b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1775c40d0f55SPeter Brune 
1776d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1777d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1778d8f46077SPeter Brune   snes->mf_version  = 1;
1779d8f46077SPeter Brune 
17803d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
17813d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
17823d4c4710SBarry Smith 
1783349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
178476bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1785349187a7SBarry Smith 
17864fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
17874fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
17884fc747eaSLawrence Mitchell 
17899b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
17904dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1791f5af7f23SKarl Rupp 
17929b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
17939b94acceSBarry Smith   kctx->version     = 2;
17940f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
17959b94acceSBarry Smith                              this was too large for some test cases */
179675567043SBarry Smith   kctx->rtol_last   = 0.0;
17970f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
17989b94acceSBarry Smith   kctx->gamma       = 1.0;
17990f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
180071f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
18010f0abf79SStefano Zampini   kctx->threshold   = 0.1;
180275567043SBarry Smith   kctx->lresid_last = 0.0;
180375567043SBarry Smith   kctx->norm_last   = 0.0;
18049b94acceSBarry Smith 
18050f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
18060f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
18070f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
18080f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
18090f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
18100f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
18110f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
18120f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
18130f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
18140f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
18150f0abf79SStefano Zampini 
18169b94acceSBarry Smith   *outsnes = snes;
18173a40ed3dSBarry Smith   PetscFunctionReturn(0);
18189b94acceSBarry Smith }
18199b94acceSBarry Smith 
182088f0584fSBarry Smith /*MC
1821f6dfbefdSBarry Smith     SNESFunction - Functional form used to convey the nonlinear function to `SNES` in `SNESSetFunction()`
182288f0584fSBarry Smith 
182388f0584fSBarry Smith      Synopsis:
1824411c0326SBarry Smith      #include "petscsnes.h"
1825411c0326SBarry Smith      PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
182688f0584fSBarry Smith 
1827c3339decSBarry Smith      Collective
18281843f636SBarry Smith 
182988f0584fSBarry Smith      Input Parameters:
1830f6dfbefdSBarry Smith +     snes - the `SNES` context
183188f0584fSBarry Smith .     x    - state at which to evaluate residual
1832f6dfbefdSBarry Smith -     ctx     - optional user-defined function context, passed in with `SNESSetFunction()`
183388f0584fSBarry Smith 
183488f0584fSBarry Smith      Output Parameter:
183588f0584fSBarry Smith .     f  - vector to put residual (function value)
183688f0584fSBarry Smith 
1837878cb397SSatish Balay    Level: intermediate
1838878cb397SSatish Balay 
1839db781477SPatrick Sanan .seealso: `SNESSetFunction()`, `SNESGetFunction()`
184088f0584fSBarry Smith M*/
184188f0584fSBarry Smith 
18429b94acceSBarry Smith /*@C
18439b94acceSBarry Smith    SNESSetFunction - Sets the function evaluation routine and function
1844f6dfbefdSBarry Smith    vector for use by the `SNES` routines in solving systems of nonlinear
18459b94acceSBarry Smith    equations.
18469b94acceSBarry Smith 
1847c3339decSBarry Smith    Logically Collective
1848fee21e36SBarry Smith 
1849c7afd0dbSLois Curfman McInnes    Input Parameters:
1850f6dfbefdSBarry Smith +  snes - the `SNES` context
18516b7fb656SBarry Smith .  r - vector to store function values, may be NULL
1852f6dfbefdSBarry Smith .  f - function evaluation routine; see `SNESFunction` for calling sequence details
1853c7afd0dbSLois Curfman McInnes -  ctx - [optional] user-defined context for private data for the
18540298fd71SBarry Smith          function evaluation routine (may be NULL)
18559b94acceSBarry Smith 
185636851e7fSLois Curfman McInnes    Level: beginner
185736851e7fSLois Curfman McInnes 
1858f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunction`
18599b94acceSBarry Smith @*/
1860d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunction(SNES snes, Vec r, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
1861d71ae5a4SJacob Faibussowitsch {
18626cab3a1bSJed Brown   DM dm;
18636cab3a1bSJed Brown 
18643a40ed3dSBarry Smith   PetscFunctionBegin;
18650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1866d2a683ecSLisandro Dalcin   if (r) {
1867d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1868d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18699566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18709566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
187185385478SLisandro Dalcin     snes->vec_func = r;
1872d2a683ecSLisandro Dalcin   }
18739566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18749566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
187548a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18763a40ed3dSBarry Smith   PetscFunctionReturn(0);
18779b94acceSBarry Smith }
18789b94acceSBarry Smith 
1879e4ed7901SPeter Brune /*@C
1880e4ed7901SPeter Brune    SNESSetInitialFunction - Sets the function vector to be used as the
1881f6dfbefdSBarry Smith    initial function value at the initialization of the method.  In some
1882e4ed7901SPeter Brune    instances, the user has precomputed the function before calling
1883f6dfbefdSBarry Smith    `SNESSolve()`.  This function allows one to avoid a redundant call
1884f6dfbefdSBarry Smith    to `SNESComputeFunction()` in that case.
1885e4ed7901SPeter Brune 
1886c3339decSBarry Smith    Logically Collective
1887e4ed7901SPeter Brune 
1888e4ed7901SPeter Brune    Input Parameters:
1889f6dfbefdSBarry Smith +  snes - the `SNES` context
1890e4ed7901SPeter Brune -  f - vector to store function value
1891e4ed7901SPeter Brune 
1892e4ed7901SPeter Brune    Notes:
1893e4ed7901SPeter Brune    This should not be modified during the solution procedure.
1894e4ed7901SPeter Brune 
1895f6dfbefdSBarry Smith    This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1896e4ed7901SPeter Brune 
1897e4ed7901SPeter Brune    Level: developer
1898e4ed7901SPeter Brune 
1899f6dfbefdSBarry Smith .seealso: `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1900e4ed7901SPeter Brune @*/
1901d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1902d71ae5a4SJacob Faibussowitsch {
1903e4ed7901SPeter Brune   Vec vec_func;
1904e4ed7901SPeter Brune 
1905e4ed7901SPeter Brune   PetscFunctionBegin;
1906e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1907e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1908e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1909efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1910902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
1911902f982fSPeter Brune     PetscFunctionReturn(0);
1912902f982fSPeter Brune   }
19139566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19149566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1915f5af7f23SKarl Rupp 
1916217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
1917e4ed7901SPeter Brune   PetscFunctionReturn(0);
1918e4ed7901SPeter Brune }
1919e4ed7901SPeter Brune 
1920534ebe21SPeter Brune /*@
1921f6dfbefdSBarry Smith    SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1922f6dfbefdSBarry Smith    of the `SNES` method, when norms are computed in the solving process
1923534ebe21SPeter Brune 
1924c3339decSBarry Smith    Logically Collective
1925534ebe21SPeter Brune 
1926534ebe21SPeter Brune    Input Parameters:
1927f6dfbefdSBarry Smith +  snes - the `SNES` context
1928365a6726SPeter Brune -  normschedule - the frequency of norm computation
1929534ebe21SPeter Brune 
1930517f1916SMatthew G. Knepley    Options Database Key:
193167b8a455SSatish Balay .  -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1932517f1916SMatthew G. Knepley 
1933534ebe21SPeter Brune    Notes:
1934f6dfbefdSBarry Smith    Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1935534ebe21SPeter Brune    of the nonlinear function and the taking of its norm at every iteration to
1936534ebe21SPeter Brune    even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1937f6dfbefdSBarry Smith    `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1938534ebe21SPeter Brune    may either be monitored for convergence or not.  As these are often used as nonlinear
1939534ebe21SPeter Brune    preconditioners, monitoring the norm of their error is not a useful enterprise within
1940534ebe21SPeter Brune    their solution.
1941534ebe21SPeter Brune 
1942f6dfbefdSBarry Smith    Level: advanced
1943534ebe21SPeter Brune 
1944f6dfbefdSBarry Smith .seealso: `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1945534ebe21SPeter Brune @*/
1946d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1947d71ae5a4SJacob Faibussowitsch {
1948534ebe21SPeter Brune   PetscFunctionBegin;
1949534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1950365a6726SPeter Brune   snes->normschedule = normschedule;
1951534ebe21SPeter Brune   PetscFunctionReturn(0);
1952534ebe21SPeter Brune }
1953534ebe21SPeter Brune 
1954534ebe21SPeter Brune /*@
1955f6dfbefdSBarry Smith    SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1956f6dfbefdSBarry Smith    of the `SNES` method.
1957534ebe21SPeter Brune 
1958c3339decSBarry Smith    Logically Collective
1959534ebe21SPeter Brune 
1960534ebe21SPeter Brune    Input Parameters:
1961f6dfbefdSBarry Smith +  snes - the `SNES` context
1962365a6726SPeter Brune -  normschedule - the type of the norm used
1963534ebe21SPeter Brune 
1964534ebe21SPeter Brune    Level: advanced
1965534ebe21SPeter Brune 
1966f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1967534ebe21SPeter Brune @*/
1968d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1969d71ae5a4SJacob Faibussowitsch {
1970534ebe21SPeter Brune   PetscFunctionBegin;
1971534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1972365a6726SPeter Brune   *normschedule = snes->normschedule;
1973534ebe21SPeter Brune   PetscFunctionReturn(0);
1974534ebe21SPeter Brune }
1975534ebe21SPeter Brune 
1976c5ce4427SMatthew G. Knepley /*@
1977c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1978c5ce4427SMatthew G. Knepley 
1979c3339decSBarry Smith   Logically Collective
1980c5ce4427SMatthew G. Knepley 
1981c5ce4427SMatthew G. Knepley   Input Parameters:
1982f6dfbefdSBarry Smith +  snes - the `SNES` context
1983f6dfbefdSBarry Smith -  norm - the value of the norm
1984c5ce4427SMatthew G. Knepley 
1985c5ce4427SMatthew G. Knepley   Level: developer
1986c5ce4427SMatthew G. Knepley 
1987f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1988c5ce4427SMatthew G. Knepley @*/
1989d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1990d71ae5a4SJacob Faibussowitsch {
1991c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1992c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1993c5ce4427SMatthew G. Knepley   snes->norm = norm;
1994c5ce4427SMatthew G. Knepley   PetscFunctionReturn(0);
1995c5ce4427SMatthew G. Knepley }
1996c5ce4427SMatthew G. Knepley 
1997c5ce4427SMatthew G. Knepley /*@
1998c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
1999c5ce4427SMatthew G. Knepley 
2000c5ce4427SMatthew G. Knepley   Not Collective
2001c5ce4427SMatthew G. Knepley 
2002c5ce4427SMatthew G. Knepley   Input Parameter:
2003f6dfbefdSBarry Smith . snes - the `SNES` context
2004c5ce4427SMatthew G. Knepley 
2005c5ce4427SMatthew G. Knepley   Output Parameter:
2006c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2007c5ce4427SMatthew G. Knepley 
2008c5ce4427SMatthew G. Knepley   Level: developer
2009c5ce4427SMatthew G. Knepley 
2010f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2011c5ce4427SMatthew G. Knepley @*/
2012d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2013d71ae5a4SJacob Faibussowitsch {
2014c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2015c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2016dadcf809SJacob Faibussowitsch   PetscValidRealPointer(norm, 2);
2017c5ce4427SMatthew G. Knepley   *norm = snes->norm;
2018c5ce4427SMatthew G. Knepley   PetscFunctionReturn(0);
2019c5ce4427SMatthew G. Knepley }
2020c5ce4427SMatthew G. Knepley 
2021c1e67a49SFande Kong /*@
2022f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2023c1e67a49SFande Kong 
2024c1e67a49SFande Kong   Not Collective
2025c1e67a49SFande Kong 
2026c1e67a49SFande Kong   Input Parameter:
2027f6dfbefdSBarry Smith . snes - the `SNES` context
2028c1e67a49SFande Kong 
2029c1e67a49SFande Kong   Output Parameter:
2030c1e67a49SFande Kong . ynorm - the last computed update norm
2031c1e67a49SFande Kong 
2032c1e67a49SFande Kong   Level: developer
2033c1e67a49SFande Kong 
2034f6dfbefdSBarry Smith   Note:
2035f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2036f6dfbefdSBarry Smith 
2037f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2038c1e67a49SFande Kong @*/
2039d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2040d71ae5a4SJacob Faibussowitsch {
2041c1e67a49SFande Kong   PetscFunctionBegin;
2042c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2043dadcf809SJacob Faibussowitsch   PetscValidRealPointer(ynorm, 2);
2044c1e67a49SFande Kong   *ynorm = snes->ynorm;
2045c1e67a49SFande Kong   PetscFunctionReturn(0);
2046c1e67a49SFande Kong }
2047c1e67a49SFande Kong 
2048c1e67a49SFande Kong /*@
20494591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2050c1e67a49SFande Kong 
2051c1e67a49SFande Kong   Not Collective
2052c1e67a49SFande Kong 
2053c1e67a49SFande Kong   Input Parameter:
2054f6dfbefdSBarry Smith . snes - the `SNES` context
2055c1e67a49SFande Kong 
2056c1e67a49SFande Kong   Output Parameter:
2057c1e67a49SFande Kong . xnorm - the last computed solution norm
2058c1e67a49SFande Kong 
2059c1e67a49SFande Kong   Level: developer
2060c1e67a49SFande Kong 
2061f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2062c1e67a49SFande Kong @*/
2063d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2064d71ae5a4SJacob Faibussowitsch {
2065c1e67a49SFande Kong   PetscFunctionBegin;
2066c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2067dadcf809SJacob Faibussowitsch   PetscValidRealPointer(xnorm, 2);
2068c1e67a49SFande Kong   *xnorm = snes->xnorm;
2069c1e67a49SFande Kong   PetscFunctionReturn(0);
2070c1e67a49SFande Kong }
2071c1e67a49SFande Kong 
207247073ea2SPeter Brune /*@C
2073f6dfbefdSBarry Smith    SNESSetFunctionType - Sets the `SNESFunctionType`
2074f6dfbefdSBarry Smith    of the `SNES` method.
207547073ea2SPeter Brune 
2076c3339decSBarry Smith    Logically Collective
207747073ea2SPeter Brune 
207847073ea2SPeter Brune    Input Parameters:
2079f6dfbefdSBarry Smith +  snes - the `SNES` context
2080f6dfbefdSBarry Smith -  type - the function type
208147073ea2SPeter Brune 
208247073ea2SPeter Brune    Level: developer
208347073ea2SPeter Brune 
2084f6dfbefdSBarry Smith    Notes:
2085f6dfbefdSBarry Smith    Possible values of the function type
2086f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType`
2087f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2088f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()`
2089f6dfbefdSBarry Smith 
2090f6dfbefdSBarry Smith    Different `SNESType`s use this value in different ways
2091f6dfbefdSBarry Smith 
2092f6dfbefdSBarry Smith .seealso: `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
209347073ea2SPeter Brune @*/
2094d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2095d71ae5a4SJacob Faibussowitsch {
209647073ea2SPeter Brune   PetscFunctionBegin;
209747073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
209847073ea2SPeter Brune   snes->functype = type;
209947073ea2SPeter Brune   PetscFunctionReturn(0);
210047073ea2SPeter Brune }
210147073ea2SPeter Brune 
210247073ea2SPeter Brune /*@C
2103f6dfbefdSBarry Smith    SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
210447073ea2SPeter Brune    of the SNES method.
210547073ea2SPeter Brune 
2106c3339decSBarry Smith    Logically Collective
210747073ea2SPeter Brune 
210847073ea2SPeter Brune    Input Parameters:
2109f6dfbefdSBarry Smith +  snes - the `SNES` context
2110f6dfbefdSBarry Smith -  type - the type of the function evaluation, see `SNESSetFunctionType()`
211147073ea2SPeter Brune 
211247073ea2SPeter Brune    Level: advanced
211347073ea2SPeter Brune 
2114f6dfbefdSBarry Smith .seealso: `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
211547073ea2SPeter Brune @*/
2116d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2117d71ae5a4SJacob Faibussowitsch {
211847073ea2SPeter Brune   PetscFunctionBegin;
211947073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
212047073ea2SPeter Brune   *type = snes->functype;
2121534ebe21SPeter Brune   PetscFunctionReturn(0);
2122534ebe21SPeter Brune }
2123534ebe21SPeter Brune 
2124bf388a1fSBarry Smith /*MC
2125f6dfbefdSBarry Smith     SNESNGSFunction - function used to apply a Gauss-Seidel sweep on the nonlinear function
2126bf388a1fSBarry Smith 
2127bf388a1fSBarry Smith      Synopsis:
2128aaa7dc30SBarry Smith      #include <petscsnes.h>
2129be95d8f1SBarry Smith $    SNESNGSFunction(SNES snes,Vec x,Vec b,void *ctx);
2130bf388a1fSBarry Smith 
2131c3339decSBarry Smith      Collective
21321843f636SBarry Smith 
21331843f636SBarry Smith      Input Parameters:
2134bf388a1fSBarry Smith +  X   - solution vector
2135bf388a1fSBarry Smith .  B   - RHS vector
2136bf388a1fSBarry Smith -  ctx - optional user-defined Gauss-Seidel context
2137bf388a1fSBarry Smith 
21381843f636SBarry Smith      Output Parameter:
21391843f636SBarry Smith .  X   - solution vector
21401843f636SBarry Smith 
2141878cb397SSatish Balay    Level: intermediate
2142878cb397SSatish Balay 
2143f6dfbefdSBarry Smith .seealso: `SNESNGS`, `SNESSetNGS()`, `SNESGetNGS()`
2144bf388a1fSBarry Smith M*/
2145bf388a1fSBarry Smith 
2146c79ef259SPeter Brune /*@C
2147be95d8f1SBarry Smith    SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2148c79ef259SPeter Brune    use with composed nonlinear solvers.
2149c79ef259SPeter Brune 
2150c79ef259SPeter Brune    Input Parameters:
2151c79ef259SPeter Brune +  snes   - the SNES context
2152f6dfbefdSBarry Smith .  f - function evaluation routine to apply Gauss-Seidel see `SNESNGSFunction`
2153c79ef259SPeter Brune -  ctx    - [optional] user-defined context for private data for the
21540298fd71SBarry Smith             smoother evaluation routine (may be NULL)
2155c79ef259SPeter Brune 
2156f6dfbefdSBarry Smith    Calling sequence of f:
2157f6dfbefdSBarry Smith $  PetscErrorCode f(SNES snes,Vec X,Vec B,void *ctx);
2158f6dfbefdSBarry Smith 
2159f6dfbefdSBarry Smith    Arguments of f:
2160f6dfbefdSBarry Smith +  snes - the `SNES` context
2161f6dfbefdSBarry Smith .  X - the current solution
2162f6dfbefdSBarry Smith .  B - the right hand side vector (which may be NULL)
2163f6dfbefdSBarry Smith -  ctx - a user provided context
2164f6dfbefdSBarry Smith 
2165f6dfbefdSBarry Smith    Note:
2166f6dfbefdSBarry Smith    The `SNESNGS` routines are used by the composed nonlinear solver to generate
2167f6dfbefdSBarry Smith     a problem appropriate update to the solution, particularly `SNESFAS`.
2168c79ef259SPeter Brune 
2169d28543b3SPeter Brune    Level: intermediate
2170c79ef259SPeter Brune 
2171f6dfbefdSBarry Smith .seealso: `SNESGetNGS()`, `SNESNGSFunction`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`
2172c79ef259SPeter Brune @*/
2173d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNGS(SNES snes, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
2174d71ae5a4SJacob Faibussowitsch {
21756cab3a1bSJed Brown   DM dm;
21766cab3a1bSJed Brown 
2177646217ecSPeter Brune   PetscFunctionBegin;
21786cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21799566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21809566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
2181646217ecSPeter Brune   PetscFunctionReturn(0);
2182646217ecSPeter Brune }
2183646217ecSPeter Brune 
2184bbc1464cSBarry Smith /*
2185bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2186bbc1464cSBarry Smith    changed during the KSPSolve()
2187bbc1464cSBarry Smith */
2188d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2189d71ae5a4SJacob Faibussowitsch {
2190bbc1464cSBarry Smith   DM     dm;
2191bbc1464cSBarry Smith   DMSNES sdm;
2192bbc1464cSBarry Smith 
2193bbc1464cSBarry Smith   PetscFunctionBegin;
21949566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21959566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2196bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2197bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2198792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21999566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22000df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2201ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2202792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22039566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2204bbc1464cSBarry Smith   } else {
2205792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22069566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2207bbc1464cSBarry Smith   }
2208bbc1464cSBarry Smith   PetscFunctionReturn(0);
2209bbc1464cSBarry Smith }
2210bbc1464cSBarry Smith 
2211d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2212d71ae5a4SJacob Faibussowitsch {
2213e03ab78fSPeter Brune   DM     dm;
2214942e3340SBarry Smith   DMSNES sdm;
22156cab3a1bSJed Brown 
22168b0a5094SBarry Smith   PetscFunctionBegin;
22179566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22189566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22198b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2220bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2221792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22229566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2223792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22249566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2225bbc1464cSBarry Smith   } else {
2226792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22279566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2228bbc1464cSBarry Smith   }
22298b0a5094SBarry Smith   PetscFunctionReturn(0);
22308b0a5094SBarry Smith }
22318b0a5094SBarry Smith 
2232d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2233d71ae5a4SJacob Faibussowitsch {
22348b0a5094SBarry Smith   PetscFunctionBegin;
2235e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2236bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22379566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22389566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22398b0a5094SBarry Smith   PetscFunctionReturn(0);
22408b0a5094SBarry Smith }
22418b0a5094SBarry Smith 
22428b0a5094SBarry Smith /*@C
2243f6dfbefdSBarry Smith    SNESSetPicard - Use `SNES` to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization)
22448b0a5094SBarry Smith 
2245c3339decSBarry Smith    Logically Collective
22468b0a5094SBarry Smith 
22478b0a5094SBarry Smith    Input Parameters:
2248f6dfbefdSBarry Smith +  snes - the `SNES` context
22496b7fb656SBarry Smith .  r - vector to store function values, may be NULL
22506b7fb656SBarry Smith .  bp - function evaluation routine, may be NULL
22516b7fb656SBarry Smith .  Amat - matrix with which A(x) x - bp(x) - b is to be computed
2252e5d3d808SBarry Smith .  Pmat - matrix from which preconditioner is computed (usually the same as Amat)
22536b7fb656SBarry Smith .  J  - function to compute matrix values, see SNESJacobianFunction() for details on its calling sequence
22546b7fb656SBarry Smith -  ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
22558b0a5094SBarry Smith 
22568b0a5094SBarry Smith    Notes:
22576b7fb656SBarry Smith     It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2258f450aa47SBarry 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.
2259f450aa47SBarry Smith 
2260f6dfbefdSBarry Smith     One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22618b0a5094SBarry Smith 
22626b7fb656SBarry 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}
22636b7fb656SBarry Smith $     Note that when an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration.
22648b0a5094SBarry Smith 
22658b0a5094SBarry Smith      Run with -snes_mf_operator to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22668b0a5094SBarry Smith 
22670d04baf8SBarry Smith    We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22686b7fb656SBarry Smith    the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b
22698b0a5094SBarry Smith 
22708b0a5094SBarry 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
22718b0a5094SBarry 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
22728b0a5094SBarry Smith    different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
22738b0a5094SBarry Smith 
2274f6dfbefdSBarry 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
2275f6dfbefdSBarry Smith     A(x^{n}) is used to build the preconditioner
22766b7fb656SBarry Smith 
22776b7fb656SBarry 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.
22786b7fb656SBarry Smith 
22796b7fb656SBarry 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
22806b7fb656SBarry 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
2281f6dfbefdSBarry 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`.
22826b7fb656SBarry Smith    See the commment in src/snes/tutorials/ex15.c.
2283bbc1464cSBarry Smith 
2284f450aa47SBarry Smith    Level: intermediate
22858b0a5094SBarry Smith 
2286f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, `SNESJacobianFunction`
22878b0a5094SBarry Smith @*/
2288d71ae5a4SJacob 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)
2289d71ae5a4SJacob Faibussowitsch {
2290e03ab78fSPeter Brune   DM dm;
2291e03ab78fSPeter Brune 
22928b0a5094SBarry Smith   PetscFunctionBegin;
22938b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22949566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22959566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22969566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22979566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22989566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22998b0a5094SBarry Smith   PetscFunctionReturn(0);
23008b0a5094SBarry Smith }
23018b0a5094SBarry Smith 
23027971a8bfSPeter Brune /*@C
23037971a8bfSPeter Brune    SNESGetPicard - Returns the context for the Picard iteration
23047971a8bfSPeter Brune 
2305f6dfbefdSBarry Smith    Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23067971a8bfSPeter Brune 
23077971a8bfSPeter Brune    Input Parameter:
2308f6dfbefdSBarry Smith .  snes - the `SNES` context
23097971a8bfSPeter Brune 
2310d8d19677SJose E. Roman    Output Parameters:
23110298fd71SBarry Smith +  r - the function (or NULL)
2312f6dfbefdSBarry Smith .  f - the function (or NULL); see `SNESFunction` for calling sequence details
2313e4357dc4SBarry Smith .  Amat - the matrix used to defined the operation A(x) x - b(x) (or NULL)
2314e4357dc4SBarry Smith .  Pmat  - the matrix from which the preconditioner will be constructed (or NULL)
2315f6dfbefdSBarry Smith .  J - the function for matrix evaluation (or NULL); see `SNESJacobianFunction` for calling sequence details
23160298fd71SBarry Smith -  ctx - the function context (or NULL)
23177971a8bfSPeter Brune 
23187971a8bfSPeter Brune    Level: advanced
23197971a8bfSPeter Brune 
2320f6dfbefdSBarry Smith .seealso: `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunction`, `SNESJacobianFunction`
23217971a8bfSPeter Brune @*/
2322d71ae5a4SJacob 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)
2323d71ae5a4SJacob Faibussowitsch {
23247971a8bfSPeter Brune   DM dm;
23257971a8bfSPeter Brune 
23267971a8bfSPeter Brune   PetscFunctionBegin;
23277971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23289566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23299566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23309566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23319566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23327971a8bfSPeter Brune   PetscFunctionReturn(0);
23337971a8bfSPeter Brune }
23347971a8bfSPeter Brune 
2335d25893d9SBarry Smith /*@C
2336d25893d9SBarry Smith    SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the problem
2337d25893d9SBarry Smith 
2338c3339decSBarry Smith    Logically Collective
2339d25893d9SBarry Smith 
2340d25893d9SBarry Smith    Input Parameters:
2341f6dfbefdSBarry Smith +  snes - the `SNES` context
2342d25893d9SBarry Smith .  func - function evaluation routine
2343d25893d9SBarry Smith -  ctx - [optional] user-defined context for private data for the
23440298fd71SBarry Smith          function evaluation routine (may be NULL)
2345d25893d9SBarry Smith 
2346d25893d9SBarry Smith    Calling sequence of func:
2347d25893d9SBarry Smith $    func (SNES snes,Vec x,void *ctx);
2348d25893d9SBarry Smith 
2349d25893d9SBarry Smith .  f - function vector
2350d25893d9SBarry Smith -  ctx - optional user-defined function context
2351d25893d9SBarry Smith 
2352d25893d9SBarry Smith    Level: intermediate
2353d25893d9SBarry Smith 
2354f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`
2355d25893d9SBarry Smith @*/
2356d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeInitialGuess(SNES snes, PetscErrorCode (*func)(SNES, Vec, void *), void *ctx)
2357d71ae5a4SJacob Faibussowitsch {
2358d25893d9SBarry Smith   PetscFunctionBegin;
2359d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2360d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2361d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
2362d25893d9SBarry Smith   PetscFunctionReturn(0);
2363d25893d9SBarry Smith }
2364d25893d9SBarry Smith 
23651096aae1SMatthew Knepley /*@C
23661096aae1SMatthew Knepley    SNESGetRhs - Gets the vector for solving F(x) = rhs. If rhs is not set
23671096aae1SMatthew Knepley    it assumes a zero right hand side.
23681096aae1SMatthew Knepley 
2369c3339decSBarry Smith    Logically Collective
23701096aae1SMatthew Knepley 
23711096aae1SMatthew Knepley    Input Parameter:
2372f6dfbefdSBarry Smith .  snes - the `SNES` context
23731096aae1SMatthew Knepley 
23741096aae1SMatthew Knepley    Output Parameter:
23750298fd71SBarry Smith .  rhs - the right hand side vector or NULL if the right hand side vector is null
23761096aae1SMatthew Knepley 
23771096aae1SMatthew Knepley    Level: intermediate
23781096aae1SMatthew Knepley 
2379f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23801096aae1SMatthew Knepley @*/
2381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2382d71ae5a4SJacob Faibussowitsch {
23831096aae1SMatthew Knepley   PetscFunctionBegin;
23840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23851096aae1SMatthew Knepley   PetscValidPointer(rhs, 2);
238685385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23871096aae1SMatthew Knepley   PetscFunctionReturn(0);
23881096aae1SMatthew Knepley }
23891096aae1SMatthew Knepley 
23909b94acceSBarry Smith /*@
2391f6dfbefdSBarry Smith    SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23929b94acceSBarry Smith 
2393c3339decSBarry Smith    Collective
2394c7afd0dbSLois Curfman McInnes 
23959b94acceSBarry Smith    Input Parameters:
2396f6dfbefdSBarry Smith +  snes - the `SNES` context
2397c7afd0dbSLois Curfman McInnes -  x - input vector
23989b94acceSBarry Smith 
23999b94acceSBarry Smith    Output Parameter:
2400f6dfbefdSBarry Smith .  y - function vector, as set by `SNESSetFunction()`
24019b94acceSBarry Smith 
2402f6dfbefdSBarry Smith    Note:
2403f6dfbefdSBarry Smith    `SNESComputeFunction()` is typically used within nonlinear solvers
2404bbc1464cSBarry Smith    implementations, so users would not generally call this routine themselves.
240536851e7fSLois Curfman McInnes 
240636851e7fSLois Curfman McInnes    Level: developer
240736851e7fSLois Curfman McInnes 
2408f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24099b94acceSBarry Smith @*/
2410d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2411d71ae5a4SJacob Faibussowitsch {
24126cab3a1bSJed Brown   DM     dm;
2413942e3340SBarry Smith   DMSNES sdm;
24149b94acceSBarry Smith 
24153a40ed3dSBarry Smith   PetscFunctionBegin;
24160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24170700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24180700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2419c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2420c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2421e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2422184914b5SBarry Smith 
24239566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24249566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
242532f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
242648a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24279566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24288ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24298ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2430800f99ffSJeremy L Thompson     {
2431800f99ffSJeremy L Thompson       void *ctx;
2432800f99ffSJeremy L Thompson       PetscErrorCode (*computefunction)(SNES, Vec, Vec, void *);
2433800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2434800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2435800f99ffSJeremy L Thompson     }
24369566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
243748a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2438c90fad12SPeter Brune   } else if (snes->vec_rhs) {
24399566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
2440644e2e5bSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve().");
24411baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2442ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2443422a814eSBarry Smith   /*
2444422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2445422a814eSBarry Smith      propagate the value to all processes
2446422a814eSBarry Smith   */
24471baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24483a40ed3dSBarry Smith   PetscFunctionReturn(0);
24499b94acceSBarry Smith }
24509b94acceSBarry Smith 
2451c79ef259SPeter Brune /*@
2452f6dfbefdSBarry Smith    SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2453bbc1464cSBarry Smith 
2454c3339decSBarry Smith    Collective
2455bbc1464cSBarry Smith 
2456bbc1464cSBarry Smith    Input Parameters:
2457f6dfbefdSBarry Smith +  snes - the `SNES` context
2458bbc1464cSBarry Smith -  x - input vector
2459bbc1464cSBarry Smith 
2460bbc1464cSBarry Smith    Output Parameter:
2461f6dfbefdSBarry Smith .  y - function vector, as set by `SNESSetMFFunction()`
2462bbc1464cSBarry Smith 
2463bbc1464cSBarry Smith    Notes:
2464f6dfbefdSBarry Smith    `SNESComputeMFFunction()` is used within the matrix vector products called by the matrix created with `MatCreateSNESMF()`
2465bbc1464cSBarry Smith    so users would not generally call this routine themselves.
2466bbc1464cSBarry Smith 
2467f6dfbefdSBarry Smith     Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with `SNESSolve()`
2468f6dfbefdSBarry Smith     while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2469f6dfbefdSBarry 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.
2470bbc1464cSBarry Smith 
2471bbc1464cSBarry Smith    Level: developer
2472bbc1464cSBarry Smith 
2473f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2474bbc1464cSBarry Smith @*/
2475d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2476d71ae5a4SJacob Faibussowitsch {
2477bbc1464cSBarry Smith   DM     dm;
2478bbc1464cSBarry Smith   DMSNES sdm;
2479bbc1464cSBarry Smith 
2480bbc1464cSBarry Smith   PetscFunctionBegin;
2481bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2482bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2483bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2484bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2485bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2486e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2487bbc1464cSBarry Smith 
24889566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24899566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24909566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24919566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2492bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2493bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2494792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24959566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2497bbc1464cSBarry Smith   snes->nfuncs++;
2498bbc1464cSBarry Smith   /*
2499bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2500bbc1464cSBarry Smith      propagate the value to all processes
2501bbc1464cSBarry Smith   */
25021baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
2503bbc1464cSBarry Smith   PetscFunctionReturn(0);
2504bbc1464cSBarry Smith }
2505bbc1464cSBarry Smith 
2506bbc1464cSBarry Smith /*@
2507f6dfbefdSBarry Smith    SNESComputeNGS - Calls the Gauss-Seidel function that has been set with  `SNESSetNGS()`.
2508c79ef259SPeter Brune 
2509c3339decSBarry Smith    Collective
2510c79ef259SPeter Brune 
2511c79ef259SPeter Brune    Input Parameters:
2512f6dfbefdSBarry Smith +  snes - the `SNES` context
2513c79ef259SPeter Brune .  x - input vector
2514c79ef259SPeter Brune -  b - rhs vector
2515c79ef259SPeter Brune 
2516c79ef259SPeter Brune    Output Parameter:
2517c79ef259SPeter Brune .  x - new solution vector
2518c79ef259SPeter Brune 
2519f6dfbefdSBarry Smith    Note:
2520f6dfbefdSBarry Smith    `SNESComputeNGS()` is typically used within composed nonlinear solver
2521c79ef259SPeter Brune    implementations, so most users would not generally call this routine
2522c79ef259SPeter Brune    themselves.
2523c79ef259SPeter Brune 
2524c79ef259SPeter Brune    Level: developer
2525c79ef259SPeter Brune 
2526f6dfbefdSBarry Smith .seealso: `SNESNGS`, `SNESSetNGS()`, `SNESComputeFunction()`
2527c79ef259SPeter Brune @*/
2528d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2529d71ae5a4SJacob Faibussowitsch {
25306cab3a1bSJed Brown   DM     dm;
2531942e3340SBarry Smith   DMSNES sdm;
2532646217ecSPeter Brune 
2533646217ecSPeter Brune   PetscFunctionBegin;
2534646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2535064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2536064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2537064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2538064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2539e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25419566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25429566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
254322c6f798SBarry Smith   if (sdm->ops->computegs) {
25449566063dSJacob Faibussowitsch     if (b) PetscCall(VecLockReadPush(b));
2545792fecdfSBarry Smith     PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25469566063dSJacob Faibussowitsch     if (b) PetscCall(VecLockReadPop(b));
2547be95d8f1SBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25489566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
2549646217ecSPeter Brune   PetscFunctionReturn(0);
2550646217ecSPeter Brune }
2551646217ecSPeter Brune 
2552d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2553d71ae5a4SJacob Faibussowitsch {
255412837594SBarry Smith   Mat               A, B, C, D, jacobian;
2555e885f1abSBarry Smith   Vec               x = snes->vec_sol, f = snes->vec_func;
2556e885f1abSBarry Smith   PetscReal         nrm, gnorm;
255781e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
25580e276705SLisandro Dalcin   MatType           mattype;
2559e885f1abSBarry Smith   PetscInt          m, n, M, N;
2560e885f1abSBarry Smith   void             *functx;
25612cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
25623325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2563e885f1abSBarry Smith   MPI_Comm          comm;
2564e885f1abSBarry Smith   PetscInt          tabs;
256512837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
25663325ff46SBarry Smith   PetscViewerFormat format;
2567e885f1abSBarry Smith 
2568e885f1abSBarry Smith   PetscFunctionBegin;
2569d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
25709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
25719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
25729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
257318d89885SKarl Rupp   if (!complete_print) {
25749566063dSJacob Faibussowitsch     PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
25759566063dSJacob Faibussowitsch     PetscCall(PetscOptionsViewer("-snes_test_jacobian_display", "Display difference between hand-coded and finite difference Jacobians", "None", &mviewer, &format, &complete_print));
257618d89885SKarl Rupp   }
257718d89885SKarl Rupp   /* for compatibility with PETSc 3.9 and older. */
25789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
25799566063dSJacob 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));
2580d0609cedSBarry Smith   PetscOptionsEnd();
2581e885f1abSBarry Smith   if (!test) PetscFunctionReturn(0);
2582e885f1abSBarry Smith 
25839566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
25849566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
25859566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
25869566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
25879566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
258812837594SBarry Smith   if (!complete_print && !directionsprinted) {
25899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
25909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
259112837594SBarry Smith   }
259212837594SBarry Smith   if (!directionsprinted) {
25939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
25949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
259512837594SBarry Smith     directionsprinted = PETSC_TRUE;
2596e885f1abSBarry Smith   }
25971baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2598e885f1abSBarry Smith 
25999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
260012837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
260112837594SBarry Smith   else jacobian = snes->jacobian_pre;
260212837594SBarry Smith 
2603a82339d0SMatthew G. Knepley   if (!x) {
26049566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(jacobian, &x, NULL));
2605a82339d0SMatthew G. Knepley   } else {
26069566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
2607a82339d0SMatthew G. Knepley   }
2608a82339d0SMatthew G. Knepley   if (!f) {
26099566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &f));
2610a82339d0SMatthew G. Knepley   } else {
26119566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)f));
2612a82339d0SMatthew G. Knepley   }
2613a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
26149566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
26159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
26169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
261712837594SBarry Smith   while (jacobian) {
26182cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
26192cd624f9SStefano Zampini 
26202cd624f9SStefano Zampini     if (istranspose) {
26219566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
26222cd624f9SStefano Zampini       Jsave    = jacobian;
26232cd624f9SStefano Zampini       jacobian = JT;
26242cd624f9SStefano Zampini     }
26259566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
262612837594SBarry Smith     if (flg) {
262712837594SBarry Smith       A = jacobian;
26289566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
262912837594SBarry Smith     } else {
26309566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
263112837594SBarry Smith     }
2632e885f1abSBarry Smith 
26339566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
26349566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
26359566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
26369566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
26379566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
26389566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
26399566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
26409566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
26419566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2642e885f1abSBarry Smith 
26439566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
26449566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
264512837594SBarry Smith 
26469566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
26479566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26489566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
26499566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
26509566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
265112837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
26529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
265312837594SBarry Smith 
2654e885f1abSBarry Smith     if (complete_print) {
26559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
26569566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
26579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
26589566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2659e885f1abSBarry Smith     }
2660e885f1abSBarry Smith 
2661df10fb39SFande Kong     if (threshold_print || complete_print) {
2662e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2663e885f1abSBarry Smith       PetscScalar       *cvals;
2664e885f1abSBarry Smith       const PetscInt    *bcols;
2665e885f1abSBarry Smith       const PetscScalar *bvals;
2666e885f1abSBarry Smith 
26679566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
26689566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
26699566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
26709566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
26719566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
26729566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
26730e276705SLisandro Dalcin 
26749566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26759566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2676e885f1abSBarry Smith 
2677e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
26789566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
26799566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2680e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
268123a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2682e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2683e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2684e885f1abSBarry Smith             cncols += 1;
2685e885f1abSBarry Smith           }
2686e885f1abSBarry Smith         }
268748a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
26889566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
26899566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2690e885f1abSBarry Smith       }
26919566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
26929566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
26939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
26949566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
26959566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2696e885f1abSBarry Smith     }
26979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
26989566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
26999566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
27002cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
270112837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
270212837594SBarry Smith       jacobian = snes->jacobian_pre;
27039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
27049371c9d4SSatish Balay     } else jacobian = NULL;
270512837594SBarry Smith   }
27069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
27071baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
27089566063dSJacob Faibussowitsch   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
27099566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2710e885f1abSBarry Smith   PetscFunctionReturn(0);
2711e885f1abSBarry Smith }
2712e885f1abSBarry Smith 
271362fef451SLois Curfman McInnes /*@
2714f6dfbefdSBarry Smith    SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
271562fef451SLois Curfman McInnes 
2716c3339decSBarry Smith    Collective
2717c7afd0dbSLois Curfman McInnes 
271862fef451SLois Curfman McInnes    Input Parameters:
2719f6dfbefdSBarry Smith +  snes - the `SNES` context
2720c7afd0dbSLois Curfman McInnes -  x - input vector
272162fef451SLois Curfman McInnes 
272262fef451SLois Curfman McInnes    Output Parameters:
2723c7afd0dbSLois Curfman McInnes +  A - Jacobian matrix
2724f6dfbefdSBarry Smith -  B - optional matrix for building the preconditioner
2725fee21e36SBarry Smith 
2726e35cf81dSBarry Smith   Options Database Keys:
272767b8a455SSatish Balay +    -snes_lag_preconditioner <lag> - how often to rebuild preconditioner
272867b8a455SSatish Balay .    -snes_lag_jacobian <lag> - how often to rebuild Jacobian
2729455a5933SJed 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.
2730455a5933SJed 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
2731693365a8SJed Brown .    -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2732693365a8SJed Brown .    -snes_compare_explicit_draw  - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2733693365a8SJed Brown .    -snes_compare_explicit_contour  - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
27344c30e9fbSJed Brown .    -snes_compare_operator  - Make the comparison options above use the operator instead of the preconditioning matrix
273594d6a431SBarry Smith .    -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference
2736a5b23f4aSJose E. Roman .    -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences
2737c01495d3SJed Brown .    -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold
2738c01495d3SJed Brown .    -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold
2739c01495d3SJed Brown .    -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold
2740a5b23f4aSJose E. Roman .    -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences
2741a5b23f4aSJose E. Roman -    -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2742c01495d3SJed Brown 
2743f6dfbefdSBarry Smith    Note:
274462fef451SLois Curfman McInnes    Most users should not need to explicitly call this routine, as it
274562fef451SLois Curfman McInnes    is used internally within the nonlinear solvers.
274662fef451SLois Curfman McInnes 
2747f6dfbefdSBarry Smith    Developer Note:
274895452b02SPatrick Sanan     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
2749e885f1abSBarry Smith       for with the SNESType of test that has been removed.
2750e885f1abSBarry Smith 
275136851e7fSLois Curfman McInnes    Level: developer
275236851e7fSLois Curfman McInnes 
2753db781477SPatrick Sanan .seealso: `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
275462fef451SLois Curfman McInnes @*/
2755d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2756d71ae5a4SJacob Faibussowitsch {
2757ace3abfcSBarry Smith   PetscBool flag;
27586cab3a1bSJed Brown   DM        dm;
2759942e3340SBarry Smith   DMSNES    sdm;
2760e0e3a89bSBarry Smith   KSP       ksp;
27613a40ed3dSBarry Smith 
27623a40ed3dSBarry Smith   PetscFunctionBegin;
27630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
27640700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2765c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2766e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
27679566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
27689566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
27693232da50SPeter Brune 
2770ebd3b9afSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
2771fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2772fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2773f5af7f23SKarl Rupp 
27749566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2775fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
27769566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
27779566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2778ebd3b9afSBarry Smith     if (flag) {
27799566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27809566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2781ebd3b9afSBarry Smith     }
2782e35cf81dSBarry Smith     PetscFunctionReturn(0);
278337ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
278463a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
27859566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2786ebd3b9afSBarry Smith     if (flag) {
27879566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27889566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2789ebd3b9afSBarry Smith     }
2790e35cf81dSBarry Smith     PetscFunctionReturn(0);
2791e35cf81dSBarry Smith   }
2792efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
27939566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27949566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2795d728fb7dSPeter Brune     PetscFunctionReturn(0);
2796d728fb7dSPeter Brune   }
2797e35cf81dSBarry Smith 
27989566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
27999566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2800800f99ffSJeremy L Thompson   {
2801800f99ffSJeremy L Thompson     void *ctx;
2802800f99ffSJeremy L Thompson     PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *);
2803800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2804800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2805800f99ffSJeremy L Thompson   }
28069566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
28079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
280828d58a37SPierre Jolivet 
280928d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
28109566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2811a8054027SBarry Smith 
2812e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
28139566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
28143b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
28159566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
28169566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
28173b4f5425SBarry Smith     snes->lagpreconditioner = -1;
28183b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
28199566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
28209566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
282137ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
282263a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
28239566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2824d1e9a80fSBarry Smith   } else {
28259566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
28269566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2827a8054027SBarry Smith   }
2828a8054027SBarry Smith 
28299566063dSJacob Faibussowitsch   PetscCall(SNESTestJacobian(snes));
28306d84be18SBarry Smith   /* make sure user returned a correct Jacobian and preconditioner */
283194ab13aaSBarry Smith   /* PetscValidHeaderSpecific(A,MAT_CLASSID,3);
283294ab13aaSBarry Smith     PetscValidHeaderSpecific(B,MAT_CLASSID,4);   */
2833693365a8SJed Brown   {
2834693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
28359566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
28369566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
28379566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
28389566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2839693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
28400298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2841693365a8SJed Brown       PetscViewer vdraw, vstdout;
28426b3a5b13SJed Brown       PetscBool   flg;
2843693365a8SJed Brown       if (flag_operator) {
28449566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2845693365a8SJed Brown         Bexp = Bexp_mine;
2846693365a8SJed Brown       } else {
2847693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
28489566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
284994ab13aaSBarry Smith         if (flg) Bexp = B;
2850693365a8SJed Brown         else {
2851693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
28529566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2853693365a8SJed Brown           Bexp = Bexp_mine;
2854693365a8SJed Brown         }
2855693365a8SJed Brown       }
28569566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
28579566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
28589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2859693365a8SJed Brown       if (flag_draw || flag_contour) {
28609566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28619566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28620298fd71SBarry Smith       } else vdraw = NULL;
28639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
28649566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
28659566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
28669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
28679566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
28689566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
28699566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
28709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
28719566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2872693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
28739566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28749566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
28759566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2876693365a8SJed Brown       }
28779566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
28789566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
28799566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
28809566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2881693365a8SJed Brown     }
2882693365a8SJed Brown   }
28834c30e9fbSJed Brown   {
28846719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
28856719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
28869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
28879566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
28889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
28899566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
28909566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
289127b0f280SBarry Smith     if (flag_threshold) {
28929566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
28939566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
289427b0f280SBarry Smith     }
28956719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
28964c30e9fbSJed Brown       Mat           Bfd;
28974c30e9fbSJed Brown       PetscViewer   vdraw, vstdout;
2898335efc43SPeter Brune       MatColoring   coloring;
28994c30e9fbSJed Brown       ISColoring    iscoloring;
29004c30e9fbSJed Brown       MatFDColoring matfdcoloring;
29014c30e9fbSJed Brown       PetscErrorCode (*func)(SNES, Vec, Vec, void *);
29024c30e9fbSJed Brown       void     *funcctx;
29036719d8e4SJed Brown       PetscReal norm1, norm2, normmax;
29044c30e9fbSJed Brown 
29059566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
29069566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
29079566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
29089566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
29099566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
29109566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
29119566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
29129566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
29139566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
29149566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
29154c30e9fbSJed Brown 
29164c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
29179566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
29189566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
29199566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
29209566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
29219566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
29229566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
29239566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
29244c30e9fbSJed Brown 
29259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
29264c30e9fbSJed Brown       if (flag_draw || flag_contour) {
29279566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
29289566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29290298fd71SBarry Smith       } else vdraw = NULL;
29309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
29319566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
29329566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
29339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
29349566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29359566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
29369566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
29379566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
29389566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
29399566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
29409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
29419566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29424c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
29439566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29449566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
29459566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
29464c30e9fbSJed Brown       }
29479566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29486719d8e4SJed Brown 
29496719d8e4SJed Brown       if (flag_threshold) {
29506719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
29519566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
29529566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
29536719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
29546719d8e4SJed Brown           const PetscScalar *ba, *ca;
29556719d8e4SJed Brown           const PetscInt    *bj, *cj;
29566719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
29576719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
29589566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
29599566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
29605f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
29616719d8e4SJed Brown           for (j = 0; j < bn; j++) {
29626719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
29636719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
29646719d8e4SJed Brown               maxentrycol = bj[j];
29656719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
29666719d8e4SJed Brown             }
29676719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
29686719d8e4SJed Brown               maxdiffcol = bj[j];
29696719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
29706719d8e4SJed Brown             }
29716719d8e4SJed Brown             if (rdiff > maxrdiff) {
29726719d8e4SJed Brown               maxrdiffcol = bj[j];
29736719d8e4SJed Brown               maxrdiff    = rdiff;
29746719d8e4SJed Brown             }
29756719d8e4SJed Brown           }
29766719d8e4SJed Brown           if (maxrdiff > 1) {
297763a3b9bcSJacob 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));
29786719d8e4SJed Brown             for (j = 0; j < bn; j++) {
29796719d8e4SJed Brown               PetscReal rdiff;
29806719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
298148a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
29826719d8e4SJed Brown             }
298363a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
29846719d8e4SJed Brown           }
29859566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
29869566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
29876719d8e4SJed Brown         }
29886719d8e4SJed Brown       }
29899566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29909566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
29914c30e9fbSJed Brown     }
29924c30e9fbSJed Brown   }
29933a40ed3dSBarry Smith   PetscFunctionReturn(0);
29949b94acceSBarry Smith }
29959b94acceSBarry Smith 
2996bf388a1fSBarry Smith /*MC
2997f6dfbefdSBarry Smith     SNESJacobianFunction - Function used by `SNES` to compute the nonlinear Jacobian of the function to be solved by `SNES`
2998bf388a1fSBarry Smith 
2999bf388a1fSBarry Smith      Synopsis:
3000411c0326SBarry Smith      #include "petscsnes.h"
3001411c0326SBarry Smith      PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
3002bf388a1fSBarry Smith 
3003c3339decSBarry Smith      Collective
30041843f636SBarry Smith 
30051843f636SBarry Smith     Input Parameters:
30061843f636SBarry Smith +  x - input vector, the Jacobian is to be computed at this value
3007bf388a1fSBarry Smith -  ctx - [optional] user-defined Jacobian context
3008bf388a1fSBarry Smith 
30091843f636SBarry Smith     Output Parameters:
30101843f636SBarry Smith +  Amat - the matrix that defines the (approximate) Jacobian
30111843f636SBarry Smith -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
30121843f636SBarry Smith 
3013878cb397SSatish Balay    Level: intermediate
3014878cb397SSatish Balay 
3015f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESSetJacobian()`, `SNESGetJacobian()`
3016bf388a1fSBarry Smith M*/
3017bf388a1fSBarry Smith 
30189b94acceSBarry Smith /*@C
30199b94acceSBarry Smith    SNESSetJacobian - Sets the function to compute Jacobian as well as the
3020044dda88SLois Curfman McInnes    location to store the matrix.
30219b94acceSBarry Smith 
3022c3339decSBarry Smith    Logically Collective
3023c7afd0dbSLois Curfman McInnes 
30249b94acceSBarry Smith    Input Parameters:
3025f6dfbefdSBarry Smith +  snes - the `SNES` context
3026e5d3d808SBarry Smith .  Amat - the matrix that defines the (approximate) Jacobian
3027e5d3d808SBarry Smith .  Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat.
3028f6dfbefdSBarry Smith .  J - Jacobian evaluation routine (if NULL then `SNES` retains any previously set value), see `SNESJacobianFunction` for details
3029c7afd0dbSLois Curfman McInnes -  ctx - [optional] user-defined context for private data for the
30300298fd71SBarry Smith          Jacobian evaluation routine (may be NULL) (if NULL then SNES retains any previously set value)
30319b94acceSBarry Smith 
30329b94acceSBarry Smith    Notes:
3033f6dfbefdSBarry Smith    If the Amat matrix and Pmat matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
303416913363SBarry Smith    each matrix.
303516913363SBarry Smith 
3036f6dfbefdSBarry Smith    If you know the operator Amat has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3037895c21f2SBarry Smith    space to Amat and the KSP solvers will automatically use that null space as needed during the solution process.
3038895c21f2SBarry Smith 
3039f6dfbefdSBarry Smith    If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the ctx argument
3040f6dfbefdSBarry Smith    must be a `MatFDColoring`.
3041a8a26c1eSJed Brown 
3042c3cc8fd1SJed Brown    Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3043f6dfbefdSBarry Smith    example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3044c3cc8fd1SJed Brown 
304536851e7fSLois Curfman McInnes    Level: beginner
304636851e7fSLois Curfman McInnes 
3047f6dfbefdSBarry Smith .seealso: `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`, `J`,
3048db781477SPatrick Sanan           `SNESSetPicard()`, `SNESJacobianFunction`
30499b94acceSBarry Smith @*/
3050d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx)
3051d71ae5a4SJacob Faibussowitsch {
30526cab3a1bSJed Brown   DM dm;
30533a7fca6bSBarry Smith 
30543a40ed3dSBarry Smith   PetscFunctionBegin;
30550700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3056e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3057e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3058e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3059e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
30609566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30619566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3062e5d3d808SBarry Smith   if (Amat) {
30639566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
30649566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3065f5af7f23SKarl Rupp 
3066e5d3d808SBarry Smith     snes->jacobian = Amat;
30673a7fca6bSBarry Smith   }
3068e5d3d808SBarry Smith   if (Pmat) {
30699566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
30709566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3071f5af7f23SKarl Rupp 
3072e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
30733a7fca6bSBarry Smith   }
30743a40ed3dSBarry Smith   PetscFunctionReturn(0);
30759b94acceSBarry Smith }
307662fef451SLois Curfman McInnes 
3077c2aafc4cSSatish Balay /*@C
3078b4fd4287SBarry Smith    SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3079b4fd4287SBarry Smith    provided context for evaluating the Jacobian.
3080b4fd4287SBarry Smith 
3081f6dfbefdSBarry Smith    Not Collective, but `Mat` object will be parallel if `SNES` object is
3082c7afd0dbSLois Curfman McInnes 
3083b4fd4287SBarry Smith    Input Parameter:
3084b4fd4287SBarry Smith .  snes - the nonlinear solver context
3085b4fd4287SBarry Smith 
3086b4fd4287SBarry Smith    Output Parameters:
3087e5d3d808SBarry Smith +  Amat - location to stash (approximate) Jacobian matrix (or NULL)
3088e5d3d808SBarry Smith .  Pmat - location to stash matrix used to compute the preconditioner (or NULL)
3089411c0326SBarry Smith .  J - location to put Jacobian function (or NULL), see SNESJacobianFunction for details on its calling sequence
30900298fd71SBarry Smith -  ctx - location to stash Jacobian ctx (or NULL)
3091fee21e36SBarry Smith 
309236851e7fSLois Curfman McInnes    Level: advanced
309336851e7fSLois Curfman McInnes 
3094f6dfbefdSBarry Smith .seealso: `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFunction`, `SNESGetFunction()`
3095b4fd4287SBarry Smith @*/
3096d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx)
3097d71ae5a4SJacob Faibussowitsch {
30986cab3a1bSJed Brown   DM dm;
30996cab3a1bSJed Brown 
31003a40ed3dSBarry Smith   PetscFunctionBegin;
31010700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3102e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3103e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
31049566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3105800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
31063a40ed3dSBarry Smith   PetscFunctionReturn(0);
3107b4fd4287SBarry Smith }
3108b4fd4287SBarry Smith 
3109d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3110d71ae5a4SJacob Faibussowitsch {
311158b371f3SBarry Smith   DM     dm;
311258b371f3SBarry Smith   DMSNES sdm;
311358b371f3SBarry Smith 
311458b371f3SBarry Smith   PetscFunctionBegin;
31159566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31169566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
311758b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
311858b371f3SBarry Smith     DM        dm;
311958b371f3SBarry Smith     PetscBool isdense, ismf;
312058b371f3SBarry Smith 
31219566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31229566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
31239566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
312458b371f3SBarry Smith     if (isdense) {
31259566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
312658b371f3SBarry Smith     } else if (!ismf) {
31279566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
312858b371f3SBarry Smith     }
312958b371f3SBarry Smith   }
313058b371f3SBarry Smith   PetscFunctionReturn(0);
313158b371f3SBarry Smith }
313258b371f3SBarry Smith 
31339b94acceSBarry Smith /*@
31349b94acceSBarry Smith    SNESSetUp - Sets up the internal data structures for the later use
3135272ac6f2SLois Curfman McInnes    of a nonlinear solver.
31369b94acceSBarry Smith 
3137c3339decSBarry Smith    Collective
3138fee21e36SBarry Smith 
3139c7afd0dbSLois Curfman McInnes    Input Parameters:
3140f6dfbefdSBarry Smith .  snes - the `SNES` context
3141c7afd0dbSLois Curfman McInnes 
3142f6dfbefdSBarry Smith    Note:
3143f6dfbefdSBarry Smith    For basic use of the `SNES` solvers the user need not explicitly call
3144f6dfbefdSBarry Smith    `SNESSetUp()`, since these actions will automatically occur during
3145f6dfbefdSBarry Smith    the call to `SNESSolve()`.  However, if one wishes to control this
3146f6dfbefdSBarry Smith    phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3147f6dfbefdSBarry Smith    and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3148272ac6f2SLois Curfman McInnes 
314936851e7fSLois Curfman McInnes    Level: advanced
315036851e7fSLois Curfman McInnes 
3151f6dfbefdSBarry Smith .seealso: `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
31529b94acceSBarry Smith @*/
3153d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3154d71ae5a4SJacob Faibussowitsch {
31556cab3a1bSJed Brown   DM             dm;
3156942e3340SBarry Smith   DMSNES         sdm;
3157c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
31586e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
3159*9b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
3160*9b5c1c08SStefano Zampini   Vec            f, fpc;
3161*9b5c1c08SStefano Zampini   void          *funcctx;
3162*9b5c1c08SStefano Zampini   void          *jacctx, *appctx;
3163*9b5c1c08SStefano Zampini   Mat            j, jpre;
31646b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
31656b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
31666e2a1849SPeter Brune   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
3167d1e9a80fSBarry Smith   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
31683a40ed3dSBarry Smith 
31693a40ed3dSBarry Smith   PetscFunctionBegin;
31700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31714dc4c822SBarry Smith   if (snes->setupcalled) PetscFunctionReturn(0);
31729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_Setup, snes, 0, 0, 0));
31739b94acceSBarry Smith 
317448a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
317585385478SLisandro Dalcin 
31769566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
317758c9b817SLisandro Dalcin 
31789566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31799566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
31809566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
318158b371f3SBarry Smith 
318248a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3183efd51863SBarry Smith 
318448a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3185b710008aSBarry Smith 
3186d8d34be6SBarry Smith   if (snes->linesearch) {
31879566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
31889566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3189d8d34be6SBarry Smith   }
31909e764e56SPeter Brune 
3191*9b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3192b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3193172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3194172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3195172a4300SPeter Brune   }
3196d8f46077SPeter Brune 
3197efd4aadfSBarry Smith   if (snes->npc) {
31986e2a1849SPeter Brune     /* copy the DM over */
31999566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32009566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
32016e2a1849SPeter Brune 
32029566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
32039566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
32049566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
32059566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
32069566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
32079566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
32089566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
3209*9b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
32109566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
32116e2a1849SPeter Brune 
32126e2a1849SPeter Brune     /* copy the function pointers over */
32139566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
32146e2a1849SPeter Brune 
32156e2a1849SPeter Brune     /* default to 1 iteration */
32169566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3217efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
32189566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3219a9936a0cSPeter Brune     } else {
32209566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3221a9936a0cSPeter Brune     }
32229566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
32236e2a1849SPeter Brune 
32246e2a1849SPeter Brune     /* copy the line search context over */
3225d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
32269566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
32279566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
32289566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
32299566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
32309566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
32319566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
32329566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
32336e2a1849SPeter Brune     }
3234d8d34be6SBarry Smith   }
32351baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
323648a46eb9SPierre Jolivet   if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user));
32376e2a1849SPeter Brune 
323837ec4e1aSPeter Brune   snes->jac_iter = 0;
323937ec4e1aSPeter Brune   snes->pre_iter = 0;
324037ec4e1aSPeter Brune 
3241dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
324258c9b817SLisandro Dalcin 
32439566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
324458b371f3SBarry Smith 
3245b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
32466c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3247d8d34be6SBarry Smith       if (snes->linesearch) {
32489566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
32499566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
32506c67d002SPeter Brune       }
32516c67d002SPeter Brune     }
3252d8d34be6SBarry Smith   }
32539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_Setup, snes, 0, 0, 0));
32547aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
32553a40ed3dSBarry Smith   PetscFunctionReturn(0);
32569b94acceSBarry Smith }
32579b94acceSBarry Smith 
325837596af1SLisandro Dalcin /*@
3259f6dfbefdSBarry Smith    SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
326037596af1SLisandro Dalcin 
3261c3339decSBarry Smith    Collective
326237596af1SLisandro Dalcin 
326337596af1SLisandro Dalcin    Input Parameter:
3264f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
326537596af1SLisandro Dalcin 
3266d25893d9SBarry Smith    Level: intermediate
3267d25893d9SBarry Smith 
326895452b02SPatrick Sanan    Notes:
3269f6dfbefdSBarry Smith    Call this if you wish to reuse a `SNES` but with different size vectors
327037596af1SLisandro Dalcin 
3271f6dfbefdSBarry Smith    Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3272f6dfbefdSBarry Smith 
3273f6dfbefdSBarry Smith .seealso: `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
327437596af1SLisandro Dalcin @*/
3275d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3276d71ae5a4SJacob Faibussowitsch {
327737596af1SLisandro Dalcin   PetscFunctionBegin;
327837596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3279d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
32809566063dSJacob Faibussowitsch     PetscCall((*snes->ops->userdestroy)((void **)&snes->user));
32810298fd71SBarry Smith     snes->user = NULL;
3282d25893d9SBarry Smith   }
32831baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
32848a23116dSBarry Smith 
3285dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
32861baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
32879e764e56SPeter Brune 
32881baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
32899e764e56SPeter Brune 
32909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
32919566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
32929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
32939566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
32949566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
32959566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
32969566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
32979566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
32989566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3299f5af7f23SKarl Rupp 
330040fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
330140fdac6aSLawrence Mitchell 
330237596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
330337596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
330437596af1SLisandro Dalcin   PetscFunctionReturn(0);
330537596af1SLisandro Dalcin }
330637596af1SLisandro Dalcin 
330752baeb72SSatish Balay /*@
3308f6dfbefdSBarry Smith    SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object.
3309c4421ceaSFande Kong 
3310c3339decSBarry Smith    Collective
3311c4421ceaSFande Kong 
3312c4421ceaSFande Kong    Input Parameter:
3313f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
3314c4421ceaSFande Kong 
3315c4421ceaSFande Kong    Level: intermediate
3316c4421ceaSFande Kong 
3317f6dfbefdSBarry Smith .seealso: `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`
3318c4421ceaSFande Kong @*/
3319d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3320d71ae5a4SJacob Faibussowitsch {
3321c4421ceaSFande Kong   PetscInt i;
3322c4421ceaSFande Kong 
3323c4421ceaSFande Kong   PetscFunctionBegin;
3324c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3325c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
332648a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3327c4421ceaSFande Kong   }
3328c4421ceaSFande Kong   snes->numberreasonviews = 0;
3329c4421ceaSFande Kong   PetscFunctionReturn(0);
3330c4421ceaSFande Kong }
3331c4421ceaSFande Kong 
33321fb7b255SJunchao Zhang /*@C
33339b94acceSBarry Smith    SNESDestroy - Destroys the nonlinear solver context that was created
3334f6dfbefdSBarry Smith    with `SNESCreate()`.
33359b94acceSBarry Smith 
3336c3339decSBarry Smith    Collective
3337c7afd0dbSLois Curfman McInnes 
33389b94acceSBarry Smith    Input Parameter:
3339f6dfbefdSBarry Smith .  snes - the `SNES` context
33409b94acceSBarry Smith 
334136851e7fSLois Curfman McInnes    Level: beginner
334236851e7fSLois Curfman McInnes 
3343f6dfbefdSBarry Smith .seealso: `SNES`, `SNESCreate()`, `SNESSolve()`
33449b94acceSBarry Smith @*/
3345d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3346d71ae5a4SJacob Faibussowitsch {
33473a40ed3dSBarry Smith   PetscFunctionBegin;
33486bf464f9SBarry Smith   if (!*snes) PetscFunctionReturn(0);
33496bf464f9SBarry Smith   PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1);
33509371c9d4SSatish Balay   if (--((PetscObject)(*snes))->refct > 0) {
33519371c9d4SSatish Balay     *snes = NULL;
33529371c9d4SSatish Balay     PetscFunctionReturn(0);
33539371c9d4SSatish Balay   }
3354d4bb536fSBarry Smith 
33559566063dSJacob Faibussowitsch   PetscCall(SNESReset((*snes)));
33569566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
33576b8b9a38SLisandro Dalcin 
3358e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
33599566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3360dbbe0bcdSBarry Smith   PetscTryTypeMethod((*snes), destroy);
33616d4c513bSLisandro Dalcin 
33629566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
33639566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
33649566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
33659566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
33666b8b9a38SLisandro Dalcin 
33679566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
336848a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
336948a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
33709566063dSJacob Faibussowitsch   PetscCall(SNESMonitorCancel((*snes)));
33719566063dSJacob Faibussowitsch   PetscCall(SNESConvergedReasonViewCancel((*snes)));
33729566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
33733a40ed3dSBarry Smith   PetscFunctionReturn(0);
33749b94acceSBarry Smith }
33759b94acceSBarry Smith 
33769b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
33779b94acceSBarry Smith 
3378a8054027SBarry Smith /*@
3379a8054027SBarry Smith    SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3380a8054027SBarry Smith 
3381c3339decSBarry Smith    Logically Collective
3382a8054027SBarry Smith 
3383a8054027SBarry Smith    Input Parameters:
3384f6dfbefdSBarry Smith +  snes - the `SNES` context
3385d8e291bfSBarry Smith -  lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
33863b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3387a8054027SBarry Smith 
3388a8054027SBarry Smith    Options Database Keys:
33893d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
33903d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
33913d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
33923d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3393a8054027SBarry Smith 
3394a8054027SBarry Smith    Notes:
3395a8054027SBarry Smith    The default is 1
3396f6dfbefdSBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3397d8e291bfSBarry Smith 
3398f6dfbefdSBarry Smith    `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3399a8054027SBarry Smith 
3400a8054027SBarry Smith    Level: intermediate
3401a8054027SBarry Smith 
3402db781477SPatrick Sanan .seealso: `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3403f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3404a8054027SBarry Smith @*/
3405d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3406d71ae5a4SJacob Faibussowitsch {
3407a8054027SBarry Smith   PetscFunctionBegin;
34080700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34095f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
34105f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3411c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3412a8054027SBarry Smith   snes->lagpreconditioner = lag;
3413a8054027SBarry Smith   PetscFunctionReturn(0);
3414a8054027SBarry Smith }
3415a8054027SBarry Smith 
3416efd51863SBarry Smith /*@
3417f6dfbefdSBarry Smith    SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3418efd51863SBarry Smith 
3419c3339decSBarry Smith    Logically Collective
3420efd51863SBarry Smith 
3421efd51863SBarry Smith    Input Parameters:
3422f6dfbefdSBarry Smith +  snes - the `SNES` context
3423efd51863SBarry Smith -  steps - the number of refinements to do, defaults to 0
3424efd51863SBarry Smith 
3425f6dfbefdSBarry Smith    Options Database Key:
342667b8a455SSatish Balay .    -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3427efd51863SBarry Smith 
3428efd51863SBarry Smith    Level: intermediate
3429efd51863SBarry Smith 
3430f6dfbefdSBarry Smith    Note:
3431f6dfbefdSBarry Smith    Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3432c0df2a02SJed Brown 
3433f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`
3434efd51863SBarry Smith @*/
3435d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3436d71ae5a4SJacob Faibussowitsch {
3437efd51863SBarry Smith   PetscFunctionBegin;
3438efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3439efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3440efd51863SBarry Smith   snes->gridsequence = steps;
3441efd51863SBarry Smith   PetscFunctionReturn(0);
3442efd51863SBarry Smith }
3443efd51863SBarry Smith 
3444fa19ca70SBarry Smith /*@
3445f6dfbefdSBarry Smith    SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3446fa19ca70SBarry Smith 
3447c3339decSBarry Smith    Logically Collective
3448fa19ca70SBarry Smith 
3449fa19ca70SBarry Smith    Input Parameter:
3450f6dfbefdSBarry Smith .  snes - the `SNES` context
3451fa19ca70SBarry Smith 
3452fa19ca70SBarry Smith    Output Parameter:
3453fa19ca70SBarry Smith .  steps - the number of refinements to do, defaults to 0
3454fa19ca70SBarry Smith 
3455f6dfbefdSBarry Smith    Options Database Key:
345667b8a455SSatish Balay .    -snes_grid_sequence <steps> - set number of refinements
3457fa19ca70SBarry Smith 
3458fa19ca70SBarry Smith    Level: intermediate
3459fa19ca70SBarry Smith 
3460f6dfbefdSBarry Smith    Note:
3461f6dfbefdSBarry Smith    Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3462fa19ca70SBarry Smith 
3463db781477SPatrick Sanan .seealso: `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3464fa19ca70SBarry Smith @*/
3465d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3466d71ae5a4SJacob Faibussowitsch {
3467fa19ca70SBarry Smith   PetscFunctionBegin;
3468fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3469fa19ca70SBarry Smith   *steps = snes->gridsequence;
3470fa19ca70SBarry Smith   PetscFunctionReturn(0);
3471fa19ca70SBarry Smith }
3472fa19ca70SBarry Smith 
3473a8054027SBarry Smith /*@
3474f6dfbefdSBarry Smith    SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3475a8054027SBarry Smith 
34763f9fe445SBarry Smith    Not Collective
3477a8054027SBarry Smith 
3478a8054027SBarry Smith    Input Parameter:
3479f6dfbefdSBarry Smith .  snes - the `SNES` context
3480a8054027SBarry Smith 
3481a8054027SBarry Smith    Output Parameter:
3482a8054027SBarry 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
34833b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3484a8054027SBarry Smith 
3485a8054027SBarry Smith    Options Database Keys:
34863d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
34873d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
34883d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
34893d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3490a8054027SBarry Smith 
3491a8054027SBarry Smith    Notes:
3492a8054027SBarry Smith    The default is 1
3493f6dfbefdSBarry Smith 
3494a8054027SBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3495a8054027SBarry Smith 
3496a8054027SBarry Smith    Level: intermediate
3497a8054027SBarry Smith 
3498f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3499a8054027SBarry Smith @*/
3500d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3501d71ae5a4SJacob Faibussowitsch {
3502a8054027SBarry Smith   PetscFunctionBegin;
35030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3504a8054027SBarry Smith   *lag = snes->lagpreconditioner;
3505a8054027SBarry Smith   PetscFunctionReturn(0);
3506a8054027SBarry Smith }
3507a8054027SBarry Smith 
3508e35cf81dSBarry Smith /*@
3509f6dfbefdSBarry Smith    SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3510e35cf81dSBarry Smith      often the preconditioner is rebuilt.
3511e35cf81dSBarry Smith 
3512c3339decSBarry Smith    Logically Collective
3513e35cf81dSBarry Smith 
3514e35cf81dSBarry Smith    Input Parameters:
3515f6dfbefdSBarry Smith +  snes - the `SNES` context
3516e35cf81dSBarry 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
3517fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3518e35cf81dSBarry Smith 
3519e35cf81dSBarry Smith    Options Database Keys:
35203d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
35213d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
35223d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
35233d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag.
3524e35cf81dSBarry Smith 
3525e35cf81dSBarry Smith    Notes:
3526e35cf81dSBarry Smith    The default is 1
3527f6dfbefdSBarry Smith 
3528e35cf81dSBarry Smith    The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3529f6dfbefdSBarry Smith 
3530fe3ffe1eSBarry 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
3531fe3ffe1eSBarry Smith    at the next Newton step but never again (unless it is reset to another value)
3532e35cf81dSBarry Smith 
3533e35cf81dSBarry Smith    Level: intermediate
3534e35cf81dSBarry Smith 
3535f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3536e35cf81dSBarry Smith @*/
3537d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3538d71ae5a4SJacob Faibussowitsch {
3539e35cf81dSBarry Smith   PetscFunctionBegin;
35400700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35415f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35425f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3543c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3544e35cf81dSBarry Smith   snes->lagjacobian = lag;
3545e35cf81dSBarry Smith   PetscFunctionReturn(0);
3546e35cf81dSBarry Smith }
3547e35cf81dSBarry Smith 
3548e35cf81dSBarry Smith /*@
3549f6dfbefdSBarry Smith    SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3550e35cf81dSBarry Smith 
35513f9fe445SBarry Smith    Not Collective
3552e35cf81dSBarry Smith 
3553e35cf81dSBarry Smith    Input Parameter:
3554f6dfbefdSBarry Smith .  snes - the `SNES` context
3555e35cf81dSBarry Smith 
3556e35cf81dSBarry Smith    Output Parameter:
3557e35cf81dSBarry 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
3558e35cf81dSBarry Smith          the Jacobian is built etc.
3559e35cf81dSBarry Smith 
3560e35cf81dSBarry Smith    Notes:
3561e35cf81dSBarry Smith    The default is 1
3562f6dfbefdSBarry Smith 
3563f6dfbefdSBarry Smith    The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3564e35cf81dSBarry Smith 
3565e35cf81dSBarry Smith    Level: intermediate
3566e35cf81dSBarry Smith 
3567f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3568e35cf81dSBarry Smith 
3569e35cf81dSBarry Smith @*/
3570d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3571d71ae5a4SJacob Faibussowitsch {
3572e35cf81dSBarry Smith   PetscFunctionBegin;
35730700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3574e35cf81dSBarry Smith   *lag = snes->lagjacobian;
3575e35cf81dSBarry Smith   PetscFunctionReturn(0);
3576e35cf81dSBarry Smith }
3577e35cf81dSBarry Smith 
357837ec4e1aSPeter Brune /*@
3579f6dfbefdSBarry Smith    SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
358037ec4e1aSPeter Brune 
3581c3339decSBarry Smith    Logically collective
358237ec4e1aSPeter Brune 
3583d8d19677SJose E. Roman    Input Parameters:
3584f6dfbefdSBarry Smith +  snes - the `SNES` context
35859d7e2deaSPeter Brune -   flg - jacobian lagging persists if true
358637ec4e1aSPeter Brune 
358737ec4e1aSPeter Brune    Options Database Keys:
35883d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
35893d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
35903d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
35913d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
35923d5a8a6aSBarry Smith 
359395452b02SPatrick Sanan    Notes:
3594f6dfbefdSBarry Smith     Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3595f6dfbefdSBarry Smith 
359695452b02SPatrick Sanan     This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
359737ec4e1aSPeter Brune    several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
359837ec4e1aSPeter Brune    timesteps may present huge efficiency gains.
359937ec4e1aSPeter Brune 
3600f6dfbefdSBarry Smith    Level: advanced
360137ec4e1aSPeter Brune 
3602f6dfbefdSBarry Smith .seealso: `SNES, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagJacobianPersists()`
360337ec4e1aSPeter Brune @*/
3604d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3605d71ae5a4SJacob Faibussowitsch {
360637ec4e1aSPeter Brune   PetscFunctionBegin;
360737ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
360837ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
360937ec4e1aSPeter Brune   snes->lagjac_persist = flg;
361037ec4e1aSPeter Brune   PetscFunctionReturn(0);
361137ec4e1aSPeter Brune }
361237ec4e1aSPeter Brune 
361337ec4e1aSPeter Brune /*@
3614d8e291bfSBarry Smith    SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
361537ec4e1aSPeter Brune 
3616c3339decSBarry Smith    Logically Collective
361737ec4e1aSPeter Brune 
3618d8d19677SJose E. Roman    Input Parameters:
3619f6dfbefdSBarry Smith +  snes - the `SNES` context
36209d7e2deaSPeter Brune -   flg - preconditioner lagging persists if true
362137ec4e1aSPeter Brune 
362237ec4e1aSPeter Brune    Options Database Keys:
36233d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
36243d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
36253d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
36263d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
362737ec4e1aSPeter Brune 
362895452b02SPatrick Sanan    Notes:
3629f6dfbefdSBarry Smith     Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3630f6dfbefdSBarry Smith 
363195452b02SPatrick Sanan    This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
363237ec4e1aSPeter Brune    by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
363337ec4e1aSPeter Brune    several timesteps may present huge efficiency gains.
363437ec4e1aSPeter Brune 
363537ec4e1aSPeter Brune    Level: developer
363637ec4e1aSPeter Brune 
3637f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
363837ec4e1aSPeter Brune @*/
3639d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3640d71ae5a4SJacob Faibussowitsch {
364137ec4e1aSPeter Brune   PetscFunctionBegin;
364237ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
364337ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
364437ec4e1aSPeter Brune   snes->lagpre_persist = flg;
364537ec4e1aSPeter Brune   PetscFunctionReturn(0);
364637ec4e1aSPeter Brune }
364737ec4e1aSPeter Brune 
36489b94acceSBarry Smith /*@
3649f6dfbefdSBarry Smith    SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3650be5caee7SBarry Smith 
3651c3339decSBarry Smith    Logically Collective
3652be5caee7SBarry Smith 
3653be5caee7SBarry Smith    Input Parameters:
3654f6dfbefdSBarry Smith +  snes - the `SNES` context
3655f6dfbefdSBarry Smith -  force - `PETSC_TRUE` require at least one iteration
3656be5caee7SBarry Smith 
3657f6dfbefdSBarry Smith    Options Database Key:
3658be5caee7SBarry Smith .    -snes_force_iteration <force> - Sets forcing an iteration
3659be5caee7SBarry Smith 
3660f6dfbefdSBarry Smith    Note:
3661f6dfbefdSBarry Smith    This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3662be5caee7SBarry Smith 
3663be5caee7SBarry Smith    Level: intermediate
3664be5caee7SBarry Smith 
3665f6dfbefdSBarry Smith .seealso: `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3666be5caee7SBarry Smith @*/
3667d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3668d71ae5a4SJacob Faibussowitsch {
3669be5caee7SBarry Smith   PetscFunctionBegin;
3670be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3671be5caee7SBarry Smith   snes->forceiteration = force;
3672be5caee7SBarry Smith   PetscFunctionReturn(0);
3673be5caee7SBarry Smith }
3674be5caee7SBarry Smith 
367585216dc7SFande Kong /*@
3676f6dfbefdSBarry Smith    SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
367785216dc7SFande Kong 
3678c3339decSBarry Smith    Logically Collective
367985216dc7SFande Kong 
368085216dc7SFande Kong    Input Parameters:
3681f6dfbefdSBarry Smith .  snes - the `SNES` context
368285216dc7SFande Kong 
368385216dc7SFande Kong    Output Parameter:
368485216dc7SFande Kong .  force - PETSC_TRUE requires at least one iteration.
368585216dc7SFande Kong 
368606dd6b0eSSatish Balay    Level: intermediate
368706dd6b0eSSatish Balay 
3688f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
368985216dc7SFande Kong @*/
3690d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3691d71ae5a4SJacob Faibussowitsch {
369285216dc7SFande Kong   PetscFunctionBegin;
369385216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
369485216dc7SFande Kong   *force = snes->forceiteration;
369585216dc7SFande Kong   PetscFunctionReturn(0);
369685216dc7SFande Kong }
3697be5caee7SBarry Smith 
3698be5caee7SBarry Smith /*@
3699f6dfbefdSBarry Smith    SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
37009b94acceSBarry Smith 
3701c3339decSBarry Smith    Logically Collective
3702c7afd0dbSLois Curfman McInnes 
37039b94acceSBarry Smith    Input Parameters:
3704f6dfbefdSBarry Smith +  snes - the `SNES` context
370570441072SBarry Smith .  abstol - absolute convergence tolerance
370633174efeSLois Curfman McInnes .  rtol - relative convergence tolerance
37075358d0d4SBarry Smith .  stol -  convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3708f6dfbefdSBarry Smith .  maxit - maximum number of iterations, default 50.
3709f6dfbefdSBarry Smith -  maxf - maximum number of function evaluations (-1 indicates no limit), default 1000
3710fee21e36SBarry Smith 
371133174efeSLois Curfman McInnes    Options Database Keys:
371270441072SBarry Smith +    -snes_atol <abstol> - Sets abstol
3713c7afd0dbSLois Curfman McInnes .    -snes_rtol <rtol> - Sets rtol
3714c7afd0dbSLois Curfman McInnes .    -snes_stol <stol> - Sets stol
3715c7afd0dbSLois Curfman McInnes .    -snes_max_it <maxit> - Sets maxit
3716c7afd0dbSLois Curfman McInnes -    -snes_max_funcs <maxf> - Sets maxf
37179b94acceSBarry Smith 
371836851e7fSLois Curfman McInnes    Level: intermediate
371936851e7fSLois Curfman McInnes 
3720f6dfbefdSBarry Smith .seealso: `SNESolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
37219b94acceSBarry Smith @*/
3722d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3723d71ae5a4SJacob Faibussowitsch {
37243a40ed3dSBarry Smith   PetscFunctionBegin;
37250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3726c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3727c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3728c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3729c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3730c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3731c5eb9154SBarry Smith 
3732ab54825eSJed Brown   if (abstol != PETSC_DEFAULT) {
37335f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3734ab54825eSJed Brown     snes->abstol = abstol;
3735ab54825eSJed Brown   }
3736ab54825eSJed Brown   if (rtol != PETSC_DEFAULT) {
37375f80ce2aSJacob 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);
3738ab54825eSJed Brown     snes->rtol = rtol;
3739ab54825eSJed Brown   }
3740ab54825eSJed Brown   if (stol != PETSC_DEFAULT) {
37415f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3742c60f73f4SPeter Brune     snes->stol = stol;
3743ab54825eSJed Brown   }
3744ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
374563a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3746ab54825eSJed Brown     snes->max_its = maxit;
3747ab54825eSJed Brown   }
3748ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
374963a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3750ab54825eSJed Brown     snes->max_funcs = maxf;
3751ab54825eSJed Brown   }
375288976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
37533a40ed3dSBarry Smith   PetscFunctionReturn(0);
37549b94acceSBarry Smith }
37559b94acceSBarry Smith 
3756e4d06f11SPatrick Farrell /*@
3757f6dfbefdSBarry Smith    SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3758e4d06f11SPatrick Farrell 
3759c3339decSBarry Smith    Logically Collective
3760e4d06f11SPatrick Farrell 
3761e4d06f11SPatrick Farrell    Input Parameters:
3762f6dfbefdSBarry Smith +  snes - the `SNES` context
3763f6dfbefdSBarry Smith -  divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3764e4d06f11SPatrick Farrell 
3765f6dfbefdSBarry Smith    Options Database Key:
3766a2b725a8SWilliam Gropp .    -snes_divergence_tolerance <divtol> - Sets divtol
3767e4d06f11SPatrick Farrell 
3768e4d06f11SPatrick Farrell    Level: intermediate
3769e4d06f11SPatrick Farrell 
3770f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3771e4d06f11SPatrick Farrell @*/
3772d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3773d71ae5a4SJacob Faibussowitsch {
3774e4d06f11SPatrick Farrell   PetscFunctionBegin;
3775e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3776e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3777e4d06f11SPatrick Farrell 
3778e4d06f11SPatrick Farrell   if (divtol != PETSC_DEFAULT) {
3779e4d06f11SPatrick Farrell     snes->divtol = divtol;
37809371c9d4SSatish Balay   } else {
3781e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3782e4d06f11SPatrick Farrell   }
3783e4d06f11SPatrick Farrell   PetscFunctionReturn(0);
3784e4d06f11SPatrick Farrell }
3785e4d06f11SPatrick Farrell 
37869b94acceSBarry Smith /*@
378733174efeSLois Curfman McInnes    SNESGetTolerances - Gets various parameters used in convergence tests.
378833174efeSLois Curfman McInnes 
3789c7afd0dbSLois Curfman McInnes    Not Collective
3790c7afd0dbSLois Curfman McInnes 
379133174efeSLois Curfman McInnes    Input Parameters:
3792f6dfbefdSBarry Smith +  snes - the `SNES` context
379385385478SLisandro Dalcin .  atol - absolute convergence tolerance
379433174efeSLois Curfman McInnes .  rtol - relative convergence tolerance
379533174efeSLois Curfman McInnes .  stol -  convergence tolerance in terms of the norm
379633174efeSLois Curfman McInnes            of the change in the solution between steps
379733174efeSLois Curfman McInnes .  maxit - maximum number of iterations
3798c7afd0dbSLois Curfman McInnes -  maxf - maximum number of function evaluations
3799fee21e36SBarry Smith 
3800f6dfbefdSBarry Smith    Note:
38010298fd71SBarry Smith    The user can specify NULL for any parameter that is not needed.
380233174efeSLois Curfman McInnes 
380336851e7fSLois Curfman McInnes    Level: intermediate
380436851e7fSLois Curfman McInnes 
3805f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetTolerances()`
380633174efeSLois Curfman McInnes @*/
3807d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3808d71ae5a4SJacob Faibussowitsch {
38093a40ed3dSBarry Smith   PetscFunctionBegin;
38100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
381185385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
381233174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3813c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
381433174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
381533174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
38163a40ed3dSBarry Smith   PetscFunctionReturn(0);
381733174efeSLois Curfman McInnes }
381833174efeSLois Curfman McInnes 
3819e4d06f11SPatrick Farrell /*@
3820e4d06f11SPatrick Farrell    SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3821e4d06f11SPatrick Farrell 
3822e4d06f11SPatrick Farrell    Not Collective
3823e4d06f11SPatrick Farrell 
3824e4d06f11SPatrick Farrell    Input Parameters:
3825f6dfbefdSBarry Smith +  snes - the `SNES` context
3826e4d06f11SPatrick Farrell -  divtol - divergence tolerance
3827e4d06f11SPatrick Farrell 
3828e4d06f11SPatrick Farrell    Level: intermediate
3829e4d06f11SPatrick Farrell 
3830f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetDivergenceTolerance()`
3831e4d06f11SPatrick Farrell @*/
3832d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3833d71ae5a4SJacob Faibussowitsch {
3834e4d06f11SPatrick Farrell   PetscFunctionBegin;
3835e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3836e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
3837e4d06f11SPatrick Farrell   PetscFunctionReturn(0);
3838e4d06f11SPatrick Farrell }
3839e4d06f11SPatrick Farrell 
384033174efeSLois Curfman McInnes /*@
38419b94acceSBarry Smith    SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
38429b94acceSBarry Smith 
3843c3339decSBarry Smith    Logically Collective
3844fee21e36SBarry Smith 
3845c7afd0dbSLois Curfman McInnes    Input Parameters:
3846f6dfbefdSBarry Smith +  snes - the `SNES` context
3847c7afd0dbSLois Curfman McInnes -  tol - tolerance
3848c7afd0dbSLois Curfman McInnes 
38499b94acceSBarry Smith    Options Database Key:
3850c7afd0dbSLois Curfman McInnes .  -snes_trtol <tol> - Sets tol
38519b94acceSBarry Smith 
385236851e7fSLois Curfman McInnes    Level: intermediate
385336851e7fSLois Curfman McInnes 
3854f6dfbefdSBarry Smith .seealso: `SNES`, `SNESNEWTONTRDC`, `SNESSetTolerances()`
38559b94acceSBarry Smith @*/
3856d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3857d71ae5a4SJacob Faibussowitsch {
38583a40ed3dSBarry Smith   PetscFunctionBegin;
38590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3860c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
38619b94acceSBarry Smith   snes->deltatol = tol;
38623a40ed3dSBarry Smith   PetscFunctionReturn(0);
38639b94acceSBarry Smith }
38649b94acceSBarry Smith 
38656ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
38666ba87a44SLisandro Dalcin 
3867d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3868d71ae5a4SJacob Faibussowitsch {
3869b271bb04SBarry Smith   PetscDrawLG      lg;
3870b271bb04SBarry Smith   PetscReal        x, y, per;
3871b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3872b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3873b271bb04SBarry Smith   PetscDraw        draw;
3874b271bb04SBarry Smith 
3875459f5d12SBarry Smith   PetscFunctionBegin;
38764d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
38779566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
38789566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38799566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38809566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3881b271bb04SBarry Smith   x = (PetscReal)n;
388277b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
388394c9c6d3SKarl Rupp   else y = -15.0;
38849566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38856934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38869566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38879566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3888b271bb04SBarry Smith   }
3889b271bb04SBarry Smith 
38909566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
38919566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38929566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38939566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "% elemts > .2*max elemt"));
38949566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3895b271bb04SBarry Smith   x = (PetscReal)n;
3896b271bb04SBarry Smith   y = 100.0 * per;
38979566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38986934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38999566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39009566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3901b271bb04SBarry Smith   }
3902b271bb04SBarry Smith 
39039566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
39049371c9d4SSatish Balay   if (!n) {
39059371c9d4SSatish Balay     prev = rnorm;
39069371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
39079371c9d4SSatish Balay   }
39089566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39099566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3910b271bb04SBarry Smith   x = (PetscReal)n;
3911b271bb04SBarry Smith   y = (prev - rnorm) / prev;
39129566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39136934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39149566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39159566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3916b271bb04SBarry Smith   }
3917b271bb04SBarry Smith 
39189566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
39199566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39209566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39219566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3922b271bb04SBarry Smith   x = (PetscReal)n;
3923b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3924b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
39259566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3926b271bb04SBarry Smith   }
39276934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39289566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39299566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3930b271bb04SBarry Smith   }
3931b271bb04SBarry Smith   prev = rnorm;
3932b271bb04SBarry Smith   PetscFunctionReturn(0);
3933b271bb04SBarry Smith }
3934b271bb04SBarry Smith 
3935228d79bcSJed Brown /*@
3936228d79bcSJed Brown    SNESMonitor - runs the user provided monitor routines, if they exist
3937228d79bcSJed Brown 
3938c3339decSBarry Smith    Collective
3939228d79bcSJed Brown 
3940228d79bcSJed Brown    Input Parameters:
3941f6dfbefdSBarry Smith +  snes - nonlinear solver context obtained from `SNESCreate()`
3942228d79bcSJed Brown .  iter - iteration number
3943228d79bcSJed Brown -  rnorm - relative norm of the residual
3944228d79bcSJed Brown 
3945f6dfbefdSBarry Smith    Note:
3946f6dfbefdSBarry Smith    This routine is called by the `SNES` implementations.
3947228d79bcSJed Brown    It does not typically need to be called by the user.
3948228d79bcSJed Brown 
3949228d79bcSJed Brown    Level: developer
3950228d79bcSJed Brown 
3951f6dfbefdSBarry Smith .seealso: `SNES`, `SNESMonitorSet()`
3952228d79bcSJed Brown @*/
3953d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
3954d71ae5a4SJacob Faibussowitsch {
39557a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
39567a03ce2fSLisandro Dalcin 
39577a03ce2fSLisandro Dalcin   PetscFunctionBegin;
39589566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
395948a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
39609566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
39617a03ce2fSLisandro Dalcin   PetscFunctionReturn(0);
39627a03ce2fSLisandro Dalcin }
39637a03ce2fSLisandro Dalcin 
39649b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
39659b94acceSBarry Smith 
3966bf388a1fSBarry Smith /*MC
3967f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
3968bf388a1fSBarry Smith 
3969bf388a1fSBarry Smith      Synopsis:
3970aaa7dc30SBarry Smith      #include <petscsnes.h>
3971bf388a1fSBarry Smith $    PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx)
3972bf388a1fSBarry Smith 
3973c3339decSBarry Smith      Collective
39741843f636SBarry Smith 
39751843f636SBarry Smith     Input Parameters:
3976f6dfbefdSBarry Smith +    snes - the `SNES` context
3977bf388a1fSBarry Smith .    its - iteration number
3978bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
3979bf388a1fSBarry Smith -    mctx - [optional] monitoring context
3980bf388a1fSBarry Smith 
3981878cb397SSatish Balay    Level: advanced
3982878cb397SSatish Balay 
3983f6dfbefdSBarry Smith .seealso: `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
3984bf388a1fSBarry Smith M*/
3985bf388a1fSBarry Smith 
39869b94acceSBarry Smith /*@C
3987a6570f20SBarry Smith    SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
39889b94acceSBarry Smith    iteration of the nonlinear solver to display the iteration's
39899b94acceSBarry Smith    progress.
39909b94acceSBarry Smith 
3991c3339decSBarry Smith    Logically Collective
3992fee21e36SBarry Smith 
3993c7afd0dbSLois Curfman McInnes    Input Parameters:
3994f6dfbefdSBarry Smith +  snes - the `SNES` context
3995f6dfbefdSBarry Smith .  f - the monitor function, see `SNESMonitorFunction` for the calling sequence
3996b8a78c4aSBarry Smith .  mctx - [optional] user-defined context for private data for the
39970298fd71SBarry Smith           monitor routine (use NULL if no context is desired)
3998b3006f0bSLois Curfman McInnes -  monitordestroy - [optional] routine that frees monitor context
39990298fd71SBarry Smith           (may be NULL)
40009b94acceSBarry Smith 
40019665c990SLois Curfman McInnes    Options Database Keys:
4002f6dfbefdSBarry Smith +    -snes_monitor        - sets `SNESMonitorDefault()`
4003798534f6SMatthew G. Knepley .    -snes_monitor draw::draw_lg - sets line graph monitor,
4004cca6129bSJed Brown -    -snes_monitor_cancel - cancels all monitors that have
4005c7afd0dbSLois Curfman McInnes                             been hardwired into a code by
4006a6570f20SBarry Smith                             calls to SNESMonitorSet(), but
4007c7afd0dbSLois Curfman McInnes                             does not cancel those set via
4008c7afd0dbSLois Curfman McInnes                             the options database.
40099665c990SLois Curfman McInnes 
4010f6dfbefdSBarry Smith    Note:
40116bc08f3fSLois Curfman McInnes    Several different monitoring routines may be set by calling
4012f6dfbefdSBarry Smith    `SNESMonitorSet()` multiple times; all will be called in the
40136bc08f3fSLois Curfman McInnes    order in which they were set.
4014639f9d9dSBarry Smith 
4015f6dfbefdSBarry Smith    Fortran Note:
4016f6dfbefdSBarry Smith    Only a single monitor function can be set for each `SNES` object
4017025f1a04SBarry Smith 
401836851e7fSLois Curfman McInnes    Level: intermediate
401936851e7fSLois Curfman McInnes 
4020f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
40219b94acceSBarry Smith @*/
4022d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4023d71ae5a4SJacob Faibussowitsch {
4024b90d0a6eSBarry Smith   PetscInt  i;
402578064530SBarry Smith   PetscBool identical;
4026b90d0a6eSBarry Smith 
40273a40ed3dSBarry Smith   PetscFunctionBegin;
40280700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4029b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
40309566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
403178064530SBarry Smith     if (identical) PetscFunctionReturn(0);
4032649052a6SBarry Smith   }
40335f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
40346e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4035b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4036639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
40373a40ed3dSBarry Smith   PetscFunctionReturn(0);
40389b94acceSBarry Smith }
40399b94acceSBarry Smith 
4040a278d85bSSatish Balay /*@
4041f6dfbefdSBarry Smith    SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
40425cd90555SBarry Smith 
4043c3339decSBarry Smith    Logically Collective
4044c7afd0dbSLois Curfman McInnes 
40455cd90555SBarry Smith    Input Parameters:
4046f6dfbefdSBarry Smith .  snes - the `SNES` context
40475cd90555SBarry Smith 
40481a480d89SAdministrator    Options Database Key:
4049a6570f20SBarry Smith .  -snes_monitor_cancel - cancels all monitors that have been hardwired
4050a6570f20SBarry Smith     into a code by calls to SNESMonitorSet(), but does not cancel those
4051c7afd0dbSLois Curfman McInnes     set via the options database
40525cd90555SBarry Smith 
4053f6dfbefdSBarry Smith    Note:
4054f6dfbefdSBarry Smith    There is no way to clear one specific monitor from a `SNES` object.
40555cd90555SBarry Smith 
405636851e7fSLois Curfman McInnes    Level: intermediate
405736851e7fSLois Curfman McInnes 
4058f6dfbefdSBarry Smith .seealso: `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
40595cd90555SBarry Smith @*/
4060d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4061d71ae5a4SJacob Faibussowitsch {
4062d952e501SBarry Smith   PetscInt i;
4063d952e501SBarry Smith 
40645cd90555SBarry Smith   PetscFunctionBegin;
40650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4066d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
406748a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4068d952e501SBarry Smith   }
40695cd90555SBarry Smith   snes->numbermonitors = 0;
40705cd90555SBarry Smith   PetscFunctionReturn(0);
40715cd90555SBarry Smith }
40725cd90555SBarry Smith 
4073bf388a1fSBarry Smith /*MC
4074bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4075bf388a1fSBarry Smith 
4076bf388a1fSBarry Smith      Synopsis:
4077aaa7dc30SBarry Smith      #include <petscsnes.h>
4078bf388a1fSBarry Smith $     PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx)
4079bf388a1fSBarry Smith 
4080c3339decSBarry Smith      Collective
40811843f636SBarry Smith 
40821843f636SBarry Smith     Input Parameters:
4083f6dfbefdSBarry Smith +    snes - the `SNES` context
4084bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4085bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4086bf388a1fSBarry Smith .    gnorm - 2-norm of current step
40871843f636SBarry Smith .    f - 2-norm of function
40881843f636SBarry Smith -    cctx - [optional] convergence context
40891843f636SBarry Smith 
40901843f636SBarry Smith     Output Parameter:
40911843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4092bf388a1fSBarry Smith 
4093878cb397SSatish Balay    Level: intermediate
4094bf388a1fSBarry Smith 
4095f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4096bf388a1fSBarry Smith M*/
4097bf388a1fSBarry Smith 
40989b94acceSBarry Smith /*@C
40999b94acceSBarry Smith    SNESSetConvergenceTest - Sets the function that is to be used
41009b94acceSBarry Smith    to test for convergence of the nonlinear iterative solution.
41019b94acceSBarry Smith 
4102c3339decSBarry Smith    Logically Collective
4103fee21e36SBarry Smith 
4104c7afd0dbSLois Curfman McInnes    Input Parameters:
4105f6dfbefdSBarry Smith +  snes - the `SNES` context
4106f6dfbefdSBarry Smith .  `SNESConvergenceTestFunction` - routine to test for convergence
41070298fd71SBarry Smith .  cctx - [optional] context for private data for the convergence routine  (may be NULL)
4108cf90aa19SBarry Smith -  destroy - [optional] destructor for the context (may be NULL; PETSC_NULL_FUNCTION in Fortran)
41099b94acceSBarry Smith 
411036851e7fSLois Curfman McInnes    Level: advanced
411136851e7fSLois Curfman McInnes 
4112f6dfbefdSBarry Smith .seealso: `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
41139b94acceSBarry Smith @*/
4114d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4115d71ae5a4SJacob Faibussowitsch {
41163a40ed3dSBarry Smith   PetscFunctionBegin;
41170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4118e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
41191baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4120bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
41217f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
412285385478SLisandro Dalcin   snes->cnvP                  = cctx;
41233a40ed3dSBarry Smith   PetscFunctionReturn(0);
41249b94acceSBarry Smith }
41259b94acceSBarry Smith 
412652baeb72SSatish Balay /*@
4127f6dfbefdSBarry Smith    SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4128184914b5SBarry Smith 
4129184914b5SBarry Smith    Not Collective
4130184914b5SBarry Smith 
4131184914b5SBarry Smith    Input Parameter:
4132f6dfbefdSBarry Smith .  snes - the `SNES` context
4133184914b5SBarry Smith 
4134184914b5SBarry Smith    Output Parameter:
4135f6dfbefdSBarry Smith .  reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4136184914b5SBarry Smith 
4137f6dfbefdSBarry Smith    Options Database Key:
41386a4d7782SBarry Smith .   -snes_converged_reason - prints the reason to standard out
41396a4d7782SBarry Smith 
4140184914b5SBarry Smith    Level: intermediate
4141184914b5SBarry Smith 
4142f6dfbefdSBarry Smith    Note:
4143f6dfbefdSBarry Smith     Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4144184914b5SBarry Smith 
4145f6dfbefdSBarry Smith .seealso: `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4146184914b5SBarry Smith @*/
4147d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4148d71ae5a4SJacob Faibussowitsch {
4149184914b5SBarry Smith   PetscFunctionBegin;
41500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41514482741eSBarry Smith   PetscValidPointer(reason, 2);
4152184914b5SBarry Smith   *reason = snes->reason;
4153184914b5SBarry Smith   PetscFunctionReturn(0);
4154184914b5SBarry Smith }
4155184914b5SBarry Smith 
4156c4421ceaSFande Kong /*@C
4157f6dfbefdSBarry Smith    SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4158c4421ceaSFande Kong 
4159c4421ceaSFande Kong    Not Collective
4160c4421ceaSFande Kong 
4161c4421ceaSFande Kong    Input Parameter:
4162f6dfbefdSBarry Smith .  snes - the `SNES` context
4163c4421ceaSFande Kong 
4164c4421ceaSFande Kong    Output Parameter:
4165c4421ceaSFande Kong .  strreason - a human readable string that describes SNES converged reason
4166c4421ceaSFande Kong 
416799c90e12SSatish Balay    Level: beginner
4168c4421ceaSFande Kong 
4169f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetConvergedReason()`
4170c4421ceaSFande Kong @*/
4171d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4172d71ae5a4SJacob Faibussowitsch {
4173c4421ceaSFande Kong   PetscFunctionBegin;
4174c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4175dadcf809SJacob Faibussowitsch   PetscValidPointer(strreason, 2);
4176c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
4177c4421ceaSFande Kong   PetscFunctionReturn(0);
4178c4421ceaSFande Kong }
4179c4421ceaSFande Kong 
418033866048SMatthew G. Knepley /*@
4181f6dfbefdSBarry Smith    SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
418233866048SMatthew G. Knepley 
418333866048SMatthew G. Knepley    Not Collective
418433866048SMatthew G. Knepley 
418533866048SMatthew G. Knepley    Input Parameters:
4186f6dfbefdSBarry Smith +  snes - the `SNES` context
4187f6dfbefdSBarry Smith -  reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
418833866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
418933866048SMatthew G. Knepley 
4190f6dfbefdSBarry Smith    Level: developer
4191f6dfbefdSBarry Smith 
4192f6dfbefdSBarry Smith    Developer Note:
4193f6dfbefdSBarry Smith    Called inside the various `SNESSolve()` implementations
419433866048SMatthew G. Knepley 
4195db781477SPatrick Sanan .seealso: `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
419633866048SMatthew G. Knepley @*/
4197d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4198d71ae5a4SJacob Faibussowitsch {
419933866048SMatthew G. Knepley   PetscFunctionBegin;
420033866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
420133866048SMatthew G. Knepley   snes->reason = reason;
420233866048SMatthew G. Knepley   PetscFunctionReturn(0);
420333866048SMatthew G. Knepley }
420433866048SMatthew G. Knepley 
4205c9005455SLois Curfman McInnes /*@
4206c9005455SLois Curfman McInnes    SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
4207c9005455SLois Curfman McInnes 
4208c3339decSBarry Smith    Logically Collective
4209fee21e36SBarry Smith 
4210c7afd0dbSLois Curfman McInnes    Input Parameters:
4211f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
42128c7482ecSBarry Smith .  a   - array to hold history, this array will contain the function norms computed at each step
4213cd5578b5SBarry Smith .  its - integer array holds the number of linear iterations for each solve.
4214758f92a0SBarry Smith .  na  - size of a and its
4215f6dfbefdSBarry Smith -  reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4216758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4217c7afd0dbSLois Curfman McInnes 
4218308dcc3eSBarry Smith    Notes:
4219f6dfbefdSBarry Smith    If 'a' and 'its' are NULL then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4220308dcc3eSBarry Smith    default array of length 10000 is allocated.
4221308dcc3eSBarry Smith 
4222c9005455SLois Curfman McInnes    This routine is useful, e.g., when running a code for purposes
4223c9005455SLois Curfman McInnes    of accurate performance monitoring, when no I/O should be done
4224c9005455SLois Curfman McInnes    during the section of code that is being timed.
4225c9005455SLois Curfman McInnes 
422636851e7fSLois Curfman McInnes    Level: intermediate
422736851e7fSLois Curfman McInnes 
4228f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4229c9005455SLois Curfman McInnes @*/
4230d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4231d71ae5a4SJacob Faibussowitsch {
42323a40ed3dSBarry Smith   PetscFunctionBegin;
42330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4234064a246eSJacob Faibussowitsch   if (a) PetscValidRealPointer(a, 2);
4235a562a398SLisandro Dalcin   if (its) PetscValidIntPointer(its, 3);
42367a1ec6d4SBarry Smith   if (!a) {
4237308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
42389566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4239071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4240308dcc3eSBarry Smith   }
4241c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4242758f92a0SBarry Smith   snes->conv_hist_its   = its;
4243115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4244a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4245758f92a0SBarry Smith   snes->conv_hist_reset = reset;
4246758f92a0SBarry Smith   PetscFunctionReturn(0);
4247758f92a0SBarry Smith }
4248758f92a0SBarry Smith 
4249d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4250c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4251c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
425299e0435eSBarry Smith 
4253d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4254d71ae5a4SJacob Faibussowitsch {
4255308dcc3eSBarry Smith   mxArray   *mat;
4256308dcc3eSBarry Smith   PetscInt   i;
4257308dcc3eSBarry Smith   PetscReal *ar;
4258308dcc3eSBarry Smith 
4259308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4260308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4261f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
426211cc89d2SBarry Smith   return mat;
4263308dcc3eSBarry Smith }
4264308dcc3eSBarry Smith #endif
4265308dcc3eSBarry Smith 
42660c4c9dddSBarry Smith /*@C
4267758f92a0SBarry Smith    SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
4268758f92a0SBarry Smith 
42693f9fe445SBarry Smith    Not Collective
4270758f92a0SBarry Smith 
4271758f92a0SBarry Smith    Input Parameter:
4272f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
4273758f92a0SBarry Smith 
4274758f92a0SBarry Smith    Output Parameters:
4275f6dfbefdSBarry Smith +  a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4276758f92a0SBarry Smith .  its - integer array holds the number of linear iterations (or
4277758f92a0SBarry Smith          negative if not converged) for each solve.
4278758f92a0SBarry Smith -  na  - size of a and its
4279758f92a0SBarry Smith 
4280758f92a0SBarry Smith    Notes:
4281758f92a0SBarry Smith     The calling sequence for this routine in Fortran is
4282758f92a0SBarry Smith $   call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4283758f92a0SBarry Smith 
4284758f92a0SBarry Smith    This routine is useful, e.g., when running a code for purposes
4285758f92a0SBarry Smith    of accurate performance monitoring, when no I/O should be done
4286758f92a0SBarry Smith    during the section of code that is being timed.
4287758f92a0SBarry Smith 
4288758f92a0SBarry Smith    Level: intermediate
4289758f92a0SBarry Smith 
4290f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4291758f92a0SBarry Smith @*/
4292d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4293d71ae5a4SJacob Faibussowitsch {
4294758f92a0SBarry Smith   PetscFunctionBegin;
42950700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4296758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4297758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4298115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
42993a40ed3dSBarry Smith   PetscFunctionReturn(0);
4300c9005455SLois Curfman McInnes }
4301c9005455SLois Curfman McInnes 
4302ac226902SBarry Smith /*@C
430376b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4304eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
43057e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
430676b2cf59SMatthew Knepley 
4307c3339decSBarry Smith   Logically Collective
430876b2cf59SMatthew Knepley 
430976b2cf59SMatthew Knepley   Input Parameters:
4310a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4311a2b725a8SWilliam Gropp - func - The function
431276b2cf59SMatthew Knepley 
431376b2cf59SMatthew Knepley   Calling sequence of func:
4314a2b725a8SWilliam Gropp $ func (SNES snes, PetscInt step);
431576b2cf59SMatthew Knepley 
431676b2cf59SMatthew Knepley . step - The current step of the iteration
431776b2cf59SMatthew Knepley 
4318fe97e370SBarry Smith   Level: advanced
4319fe97e370SBarry Smith 
43206b7fb656SBarry Smith   Note:
4321f6dfbefdSBarry 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
4322f6dfbefdSBarry Smith      to `SNESSetFunction()`, or `SNESSetPicard()`
4323fe97e370SBarry Smith      This is not used by most users.
432476b2cf59SMatthew Knepley 
43256b7fb656SBarry Smith      There are a varity of function hooks one many set that are called at different stages of the nonlinear solution process, see the functions listed below.
43266b7fb656SBarry Smith 
4327f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESSolve()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4328db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
432976b2cf59SMatthew Knepley @*/
4330d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
4331d71ae5a4SJacob Faibussowitsch {
433276b2cf59SMatthew Knepley   PetscFunctionBegin;
43330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4334e7788613SBarry Smith   snes->ops->update = func;
433576b2cf59SMatthew Knepley   PetscFunctionReturn(0);
433676b2cf59SMatthew Knepley }
433776b2cf59SMatthew Knepley 
43389b94acceSBarry Smith /*
43399b94acceSBarry Smith    SNESScaleStep_Private - Scales a step so that its length is less than the
43409b94acceSBarry Smith    positive parameter delta.
43419b94acceSBarry Smith 
43429b94acceSBarry Smith     Input Parameters:
4343f6dfbefdSBarry Smith +   snes - the `SNES` context
43449b94acceSBarry Smith .   y - approximate solution of linear system
43459b94acceSBarry Smith .   fnorm - 2-norm of current function
4346c7afd0dbSLois Curfman McInnes -   delta - trust region size
43479b94acceSBarry Smith 
43489b94acceSBarry Smith     Output Parameters:
4349c7afd0dbSLois Curfman McInnes +   gpnorm - predicted function norm at the new point, assuming local
43509b94acceSBarry Smith     linearization.  The value is zero if the step lies within the trust
43519b94acceSBarry Smith     region, and exceeds zero otherwise.
4352c7afd0dbSLois Curfman McInnes -   ynorm - 2-norm of the step
43539b94acceSBarry Smith 
4354f6dfbefdSBarry Smith     Level: developer
43559b94acceSBarry Smith 
4356f6dfbefdSBarry Smith     Note:
4357f6dfbefdSBarry Smith     For non-trust region methods such as `SNESNEWTONLS`, the parameter delta
4358f6dfbefdSBarry Smith     is set to be the maximum allowable step size.
43599b94acceSBarry Smith */
4360d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESScaleStep_Private(SNES snes, Vec y, PetscReal *fnorm, PetscReal *delta, PetscReal *gpnorm, PetscReal *ynorm)
4361d71ae5a4SJacob Faibussowitsch {
4362064f8208SBarry Smith   PetscReal   nrm;
4363ea709b57SSatish Balay   PetscScalar cnorm;
43643a40ed3dSBarry Smith 
43653a40ed3dSBarry Smith   PetscFunctionBegin;
43660700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43670700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 2);
4368c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 2);
4369184914b5SBarry Smith 
43709566063dSJacob Faibussowitsch   PetscCall(VecNorm(y, NORM_2, &nrm));
4371064f8208SBarry Smith   if (nrm > *delta) {
4372064f8208SBarry Smith     nrm     = *delta / nrm;
4373064f8208SBarry Smith     *gpnorm = (1.0 - nrm) * (*fnorm);
4374064f8208SBarry Smith     cnorm   = nrm;
43759566063dSJacob Faibussowitsch     PetscCall(VecScale(y, cnorm));
43769b94acceSBarry Smith     *ynorm = *delta;
43779b94acceSBarry Smith   } else {
43789b94acceSBarry Smith     *gpnorm = 0.0;
4379064f8208SBarry Smith     *ynorm  = nrm;
43809b94acceSBarry Smith   }
43813a40ed3dSBarry Smith   PetscFunctionReturn(0);
43829b94acceSBarry Smith }
43839b94acceSBarry Smith 
438491f3e32bSBarry Smith /*@C
4385f6dfbefdSBarry Smith    SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
43862a359c20SBarry Smith 
4387c3339decSBarry Smith    Collective
43882a359c20SBarry Smith 
43892a359c20SBarry Smith    Parameter:
4390f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
43912a359c20SBarry Smith -  viewer - the viewer to display the reason
43922a359c20SBarry Smith 
43932a359c20SBarry Smith    Options Database Keys:
4394ee300463SSatish Balay +  -snes_converged_reason - print reason for converged or diverged, also prints number of iterations
4395ee300463SSatish Balay -  -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4396eafd5ff0SAlex Lindsay 
4397f6dfbefdSBarry Smith   Note:
4398f6dfbefdSBarry Smith      To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4399f6dfbefdSBarry Smith      use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
44002a359c20SBarry Smith 
44012a359c20SBarry Smith    Level: beginner
44022a359c20SBarry Smith 
4403f6dfbefdSBarry Smith .seealso: `SNESConvergedReason`, `PetscViewer`, `SNES`,
4404f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4405f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4406db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
44072a359c20SBarry Smith @*/
4408d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4409d71ae5a4SJacob Faibussowitsch {
441075cca76cSMatthew G. Knepley   PetscViewerFormat format;
44112a359c20SBarry Smith   PetscBool         isAscii;
44122a359c20SBarry Smith 
44132a359c20SBarry Smith   PetscFunctionBegin;
441419a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
44159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
44162a359c20SBarry Smith   if (isAscii) {
44179566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
44189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
441975cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
442075cca76cSMatthew G. Knepley       DM       dm;
442175cca76cSMatthew G. Knepley       Vec      u;
442275cca76cSMatthew G. Knepley       PetscDS  prob;
442375cca76cSMatthew G. Knepley       PetscInt Nf, f;
442495cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
442595cbbfd3SMatthew G. Knepley       void    **exactCtx;
442675cca76cSMatthew G. Knepley       PetscReal error;
442775cca76cSMatthew G. Knepley 
44289566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
44299566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
44309566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
44319566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
44329566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
44339566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
44349566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
44359566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
44369566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
443763a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
443875cca76cSMatthew G. Knepley     }
4439eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
44402a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
444163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
44422a359c20SBarry Smith       } else {
444363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44442a359c20SBarry Smith       }
4445eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
44462a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
444763a3b9bcSJacob 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));
44482a359c20SBarry Smith       } else {
444963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44502a359c20SBarry Smith       }
44512a359c20SBarry Smith     }
44529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
44532a359c20SBarry Smith   }
44542a359c20SBarry Smith   PetscFunctionReturn(0);
44552a359c20SBarry Smith }
44562a359c20SBarry Smith 
4457c4421ceaSFande Kong /*@C
4458c4421ceaSFande Kong    SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4459c4421ceaSFande Kong     end of the nonlinear solver to display the conver reason of the nonlinear solver.
4460c4421ceaSFande Kong 
4461c3339decSBarry Smith    Logically Collective
4462c4421ceaSFande Kong 
4463c4421ceaSFande Kong    Input Parameters:
4464f6dfbefdSBarry Smith +  snes - the `SNES` context
4465c4421ceaSFande Kong .  f - the snes converged reason view function
4466c4421ceaSFande Kong .  vctx - [optional] user-defined context for private data for the
4467c4421ceaSFande Kong           snes converged reason view routine (use NULL if no context is desired)
4468c4421ceaSFande Kong -  reasonviewdestroy - [optional] routine that frees reasonview context
4469c4421ceaSFande Kong           (may be NULL)
4470c4421ceaSFande Kong 
4471c4421ceaSFande Kong    Options Database Keys:
4472f6dfbefdSBarry Smith +    -snes_converged_reason        - sets a default `SNESConvergedReasonView()`
4473c4421ceaSFande Kong -    -snes_converged_reason_view_cancel - cancels all converged reason viewers that have
4474c4421ceaSFande Kong                             been hardwired into a code by
4475f6dfbefdSBarry Smith                             calls to `SNESConvergedReasonViewSet()`, but
4476c4421ceaSFande Kong                             does not cancel those set via
4477c4421ceaSFande Kong                             the options database.
4478c4421ceaSFande Kong 
4479f6dfbefdSBarry Smith    Note:
4480c4421ceaSFande Kong    Several different converged reason view routines may be set by calling
4481f6dfbefdSBarry Smith    `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4482c4421ceaSFande Kong    order in which they were set.
4483c4421ceaSFande Kong 
4484c4421ceaSFande Kong    Level: intermediate
4485c4421ceaSFande Kong 
4486f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4487c4421ceaSFande Kong @*/
4488d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES, void *), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **))
4489d71ae5a4SJacob Faibussowitsch {
4490c4421ceaSFande Kong   PetscInt  i;
4491c4421ceaSFande Kong   PetscBool identical;
4492c4421ceaSFande Kong 
4493c4421ceaSFande Kong   PetscFunctionBegin;
4494c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4495c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
44969566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
4497c4421ceaSFande Kong     if (identical) PetscFunctionReturn(0);
4498c4421ceaSFande Kong   }
44995f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4500c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4501c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4502c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
4503c4421ceaSFande Kong   PetscFunctionReturn(0);
4504c4421ceaSFande Kong }
4505c4421ceaSFande Kong 
450691f3e32bSBarry Smith /*@
4507f6dfbefdSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed.
4508c4421ceaSFande Kong                                        All the user-provided convergedReasonView routines will be involved as well, if they exist.
45092a359c20SBarry Smith 
4510c3339decSBarry Smith   Collective
45112a359c20SBarry Smith 
45122a359c20SBarry Smith   Input Parameters:
4513f6dfbefdSBarry Smith . snes   - the `SNES` object
45142a359c20SBarry Smith 
4515f6dfbefdSBarry Smith   Level: advanced
45162a359c20SBarry Smith 
4517f6dfbefdSBarry Smith .seealso: `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4518f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
45192a359c20SBarry Smith @*/
4520d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4521d71ae5a4SJacob Faibussowitsch {
45222a359c20SBarry Smith   PetscViewer       viewer;
45232a359c20SBarry Smith   PetscBool         flg;
45242a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
45252a359c20SBarry Smith   PetscViewerFormat format;
4526c4421ceaSFande Kong   PetscInt          i;
45272a359c20SBarry Smith 
45282a359c20SBarry Smith   PetscFunctionBegin;
45292a359c20SBarry Smith   if (incall) PetscFunctionReturn(0);
45302a359c20SBarry Smith   incall = PETSC_TRUE;
4531c4421ceaSFande Kong 
4532c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
453348a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4534c4421ceaSFande Kong 
4535c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
45369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
45372a359c20SBarry Smith   if (flg) {
45389566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
45399566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
45409566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
45419566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
45422a359c20SBarry Smith   }
45432a359c20SBarry Smith   incall = PETSC_FALSE;
45442a359c20SBarry Smith   PetscFunctionReturn(0);
45452a359c20SBarry Smith }
45462a359c20SBarry Smith 
4547487a658cSBarry Smith /*@
4548f69a0ea3SMatthew Knepley    SNESSolve - Solves a nonlinear system F(x) = b.
4549f6dfbefdSBarry Smith    Call `SNESSolve()` after calling `SNESCreate()` and optional routines of the form `SNESSetXXX()`.
45509b94acceSBarry Smith 
4551c3339decSBarry Smith    Collective
4552c7afd0dbSLois Curfman McInnes 
4553b2002411SLois Curfman McInnes    Input Parameters:
4554f6dfbefdSBarry Smith +  snes - the `SNES` context
45550298fd71SBarry Smith .  b - the constant part of the equation F(x) = b, or NULL to use zero.
455685385478SLisandro Dalcin -  x - the solution vector.
45579b94acceSBarry Smith 
4558f6dfbefdSBarry Smith    Note:
45598ddd3da0SLois Curfman McInnes    The user should initialize the vector,x, with the initial guess
4560f6dfbefdSBarry Smith    for the nonlinear solve prior to calling `SNESSolve()`.  In particular,
45618ddd3da0SLois Curfman McInnes    to employ an initial guess of zero, the user should explicitly set
4562f6dfbefdSBarry Smith    this vector to zero by calling `VecSet()`.
45638ddd3da0SLois Curfman McInnes 
456436851e7fSLois Curfman McInnes    Level: beginner
456536851e7fSLois Curfman McInnes 
4566f6dfbefdSBarry Smith .seealso: `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4567db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4568db781477SPatrick Sanan           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
45699b94acceSBarry Smith @*/
4570d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4571d71ae5a4SJacob Faibussowitsch {
4572ace3abfcSBarry Smith   PetscBool flg;
4573efd51863SBarry Smith   PetscInt  grid;
45740298fd71SBarry Smith   Vec       xcreated = NULL;
4575caa4e7f2SJed Brown   DM        dm;
4576052efed2SBarry Smith 
45773a40ed3dSBarry Smith   PetscFunctionBegin;
45780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4579a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4580a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
45810700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
458285385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
458385385478SLisandro Dalcin 
458434b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
458506fc46c8SMatthew G. Knepley   {
458606fc46c8SMatthew G. Knepley     PetscViewer       viewer;
458706fc46c8SMatthew G. Knepley     PetscViewerFormat format;
45887c88af5aSMatthew G. Knepley     PetscInt          num;
458906fc46c8SMatthew G. Knepley     PetscBool         flg;
459006fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
459106fc46c8SMatthew G. Knepley 
459206fc46c8SMatthew G. Knepley     if (!incall) {
459334b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
45949566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
459506fc46c8SMatthew G. Knepley       if (flg) {
459606fc46c8SMatthew G. Knepley         PetscConvEst conv;
459746079b62SMatthew G. Knepley         DM           dm;
459846079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
459946079b62SMatthew G. Knepley         PetscInt     Nf;
460006fc46c8SMatthew G. Knepley 
460106fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
46029566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
46039566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
46049566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
46059566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
46069566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
46079566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
46089566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
46099566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
46109566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
46119566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
46129566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
46139566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
46149566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
46159566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
461606fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
461706fc46c8SMatthew G. Knepley       }
461834b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4619b2588ea6SMatthew G. Knepley       num = 1;
46209566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
462134b4d3a8SMatthew G. Knepley       if (flg) {
462234b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
462334b4d3a8SMatthew G. Knepley 
462434b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
46259566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46269566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46279566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46289566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46299566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46309566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
46319566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
463234b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
463334b4d3a8SMatthew G. Knepley       }
46347c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
46357c88af5aSMatthew G. Knepley       num = 0;
46369566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
46377c88af5aSMatthew G. Knepley       if (num) {
46387c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
46397c88af5aSMatthew G. Knepley 
46407c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
46419566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46429566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46439566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46449566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46459566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46469566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
46479566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
46487c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
46497c88af5aSMatthew G. Knepley       }
465006fc46c8SMatthew G. Knepley     }
465106fc46c8SMatthew G. Knepley   }
4652ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4653caa4e7f2SJed Brown   if (!x) {
46549566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
46559566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4656a69afd8bSBarry Smith     x = xcreated;
4657a69afd8bSBarry Smith   }
46589566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4659f05ece33SBarry Smith 
46609566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4661efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
466285385478SLisandro Dalcin     /* set solution vector */
46639566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
46649566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
466585385478SLisandro Dalcin     snes->vec_sol = x;
46669566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4667caa4e7f2SJed Brown 
4668caa4e7f2SJed Brown     /* set affine vector if provided */
46699566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
46709566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
467185385478SLisandro Dalcin     snes->vec_rhs = b;
467285385478SLisandro Dalcin 
46735f80ce2aSJacob 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");
46745f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
46755f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector");
46764dfa11a4SJacob Faibussowitsch     if (!snes->vec_sol_update /* && snes->vec_sol */) { PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update)); }
46779566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
46789566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
46793f149594SLisandro Dalcin 
46807eee914bSBarry Smith     if (!grid) {
468125e27a38SBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4682dd568438SSatish Balay     }
4683d25893d9SBarry Smith 
4684abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
46859371c9d4SSatish Balay     if (snes->counters_reset) {
46869371c9d4SSatish Balay       snes->nfuncs      = 0;
46879371c9d4SSatish Balay       snes->linear_its  = 0;
46889371c9d4SSatish Balay       snes->numFailures = 0;
46899371c9d4SSatish Balay     }
4690d5e45103SBarry Smith 
46919566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4692dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
46939566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
46945f80ce2aSJacob Faibussowitsch     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver returned without setting converged reason");
4695422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
46963f149594SLisandro Dalcin 
469737ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
469837ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
469937ec4e1aSPeter Brune 
47009566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
47019566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4702c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
47039566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
47045968eb51SBarry Smith 
47055f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
47069c8e83a9SBarry Smith     if (snes->reason < 0) break;
4707efd51863SBarry Smith     if (grid < snes->gridsequence) {
4708efd51863SBarry Smith       DM  fine;
4709efd51863SBarry Smith       Vec xnew;
4710efd51863SBarry Smith       Mat interp;
4711efd51863SBarry Smith 
47129566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
47135f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
47149566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
47159566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
47169566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
47179566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
47189566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4719efd51863SBarry Smith       x = xnew;
4720efd51863SBarry Smith 
47219566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
47229566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
47239566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
47249566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
47259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4726efd51863SBarry Smith     }
4727efd51863SBarry Smith   }
47289566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
47299566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
47309566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
47319566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
47323f7e2da0SPeter Brune 
47339566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
47349566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
47353a40ed3dSBarry Smith   PetscFunctionReturn(0);
47369b94acceSBarry Smith }
47379b94acceSBarry Smith 
47389b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
47399b94acceSBarry Smith 
474082bf6240SBarry Smith /*@C
47414b0e389bSBarry Smith    SNESSetType - Sets the method for the nonlinear solver.
47429b94acceSBarry Smith 
4743c3339decSBarry Smith    Collective
4744fee21e36SBarry Smith 
4745c7afd0dbSLois Curfman McInnes    Input Parameters:
4746f6dfbefdSBarry Smith +  snes - the `SNES` context
4747454a90a3SBarry Smith -  type - a known method
4748c7afd0dbSLois Curfman McInnes 
4749c7afd0dbSLois Curfman McInnes    Options Database Key:
4750454a90a3SBarry Smith .  -snes_type <type> - Sets the method; use -help for a list
475104d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4752ae12b187SLois Curfman McInnes 
47539b94acceSBarry Smith    Notes:
4754e090d566SSatish Balay    See "petsc/include/petscsnes.h" for available methods (for instance)
4755f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4756c7afd0dbSLois Curfman McInnes      (systems of nonlinear equations)
4757f6dfbefdSBarry Smith -    `SNESNEWTONTRDC` - Newton's method with trust region
4758c7afd0dbSLois Curfman McInnes      (systems of nonlinear equations)
47599b94acceSBarry Smith 
4760f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4761f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4762ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4763ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4764f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4765ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4766ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4767ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4768ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4769b0a32e0cSBarry Smith   appropriate method.
477036851e7fSLois Curfman McInnes 
4771f6dfbefdSBarry Smith     Developer Note:
4772f6dfbefdSBarry Smith     `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4773f6dfbefdSBarry Smith     the constructor in that list and calls it to create the specific object.
47748f6c3df8SBarry Smith 
477536851e7fSLois Curfman McInnes   Level: intermediate
4776a703fe33SLois Curfman McInnes 
4777f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
47789b94acceSBarry Smith @*/
4779d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4780d71ae5a4SJacob Faibussowitsch {
4781ace3abfcSBarry Smith   PetscBool match;
47825f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
47833a40ed3dSBarry Smith 
47843a40ed3dSBarry Smith   PetscFunctionBegin;
47850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47864482741eSBarry Smith   PetscValidCharPointer(type, 2);
478782bf6240SBarry Smith 
47889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
47890f5bd95cSBarry Smith   if (match) PetscFunctionReturn(0);
479092ff6ae8SBarry Smith 
47919566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
47925f80ce2aSJacob Faibussowitsch   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
479375396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4794dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
479575396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
47969e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
47979e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
47989e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
47999e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
48009e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
48017fe760d5SStefano Zampini 
48027fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
48039566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
48047fe760d5SStefano Zampini 
480575396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
480675396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4807f5af7f23SKarl Rupp 
48089566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
48099566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
48103a40ed3dSBarry Smith   PetscFunctionReturn(0);
48119b94acceSBarry Smith }
48129b94acceSBarry Smith 
48139b94acceSBarry Smith /*@C
4814f6dfbefdSBarry Smith    SNESGetType - Gets the `SNES` method type and name (as a string).
48159b94acceSBarry Smith 
4816c7afd0dbSLois Curfman McInnes    Not Collective
4817c7afd0dbSLois Curfman McInnes 
48189b94acceSBarry Smith    Input Parameter:
48194b0e389bSBarry Smith .  snes - nonlinear solver context
48209b94acceSBarry Smith 
48219b94acceSBarry Smith    Output Parameter:
4822f6dfbefdSBarry Smith .  type - `SNES` method (a character string)
48239b94acceSBarry Smith 
482436851e7fSLois Curfman McInnes    Level: intermediate
482536851e7fSLois Curfman McInnes 
4826f6dfbefdSBarry Smith .seealso: `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
48279b94acceSBarry Smith @*/
4828d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4829d71ae5a4SJacob Faibussowitsch {
48303a40ed3dSBarry Smith   PetscFunctionBegin;
48310700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48324482741eSBarry Smith   PetscValidPointer(type, 2);
48337adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
48343a40ed3dSBarry Smith   PetscFunctionReturn(0);
48359b94acceSBarry Smith }
48369b94acceSBarry Smith 
48373cd8a7caSMatthew G. Knepley /*@
4838f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
48393cd8a7caSMatthew G. Knepley 
4840c3339decSBarry Smith   Logically Collective
48413cd8a7caSMatthew G. Knepley 
48423cd8a7caSMatthew G. Knepley   Input Parameters:
4843f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
48443cd8a7caSMatthew G. Knepley - u    - the solution vector
48453cd8a7caSMatthew G. Knepley 
48463cd8a7caSMatthew G. Knepley   Level: beginner
48473cd8a7caSMatthew G. Knepley 
4848f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
48493cd8a7caSMatthew G. Knepley @*/
4850d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4851d71ae5a4SJacob Faibussowitsch {
48523cd8a7caSMatthew G. Knepley   DM dm;
48533cd8a7caSMatthew G. Knepley 
48543cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
48553cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48563cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
48579566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
48589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
48593cd8a7caSMatthew G. Knepley 
48603cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
48613cd8a7caSMatthew G. Knepley 
48629566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
48639566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
48643cd8a7caSMatthew G. Knepley   PetscFunctionReturn(0);
48653cd8a7caSMatthew G. Knepley }
48663cd8a7caSMatthew G. Knepley 
486752baeb72SSatish Balay /*@
48689b94acceSBarry Smith    SNESGetSolution - Returns the vector where the approximate solution is
4869f6dfbefdSBarry Smith    stored. This is the fine grid solution when using `SNESSetGridSequence()`.
48709b94acceSBarry Smith 
4871f6dfbefdSBarry Smith    Not Collective, but x is parallel if snes is parallel
4872c7afd0dbSLois Curfman McInnes 
48739b94acceSBarry Smith    Input Parameter:
4874f6dfbefdSBarry Smith .  snes - the `SNES` context
48759b94acceSBarry Smith 
48769b94acceSBarry Smith    Output Parameter:
48779b94acceSBarry Smith .  x - the solution
48789b94acceSBarry Smith 
487970e92668SMatthew Knepley    Level: intermediate
488036851e7fSLois Curfman McInnes 
4881f6dfbefdSBarry Smith .seealso: `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
48829b94acceSBarry Smith @*/
4883d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4884d71ae5a4SJacob Faibussowitsch {
48853a40ed3dSBarry Smith   PetscFunctionBegin;
48860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48874482741eSBarry Smith   PetscValidPointer(x, 2);
488885385478SLisandro Dalcin   *x = snes->vec_sol;
488970e92668SMatthew Knepley   PetscFunctionReturn(0);
489070e92668SMatthew Knepley }
489170e92668SMatthew Knepley 
489252baeb72SSatish Balay /*@
48939b94acceSBarry Smith    SNESGetSolutionUpdate - Returns the vector where the solution update is
48949b94acceSBarry Smith    stored.
48959b94acceSBarry Smith 
4896f6dfbefdSBarry Smith    Not Collective, but x is parallel if snes is parallel
4897c7afd0dbSLois Curfman McInnes 
48989b94acceSBarry Smith    Input Parameter:
4899f6dfbefdSBarry Smith .  snes - the `SNES` context
49009b94acceSBarry Smith 
49019b94acceSBarry Smith    Output Parameter:
49029b94acceSBarry Smith .  x - the solution update
49039b94acceSBarry Smith 
490436851e7fSLois Curfman McInnes    Level: advanced
490536851e7fSLois Curfman McInnes 
4906f6dfbefdSBarry Smith .seealso: `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
49079b94acceSBarry Smith @*/
4908d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4909d71ae5a4SJacob Faibussowitsch {
49103a40ed3dSBarry Smith   PetscFunctionBegin;
49110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49124482741eSBarry Smith   PetscValidPointer(x, 2);
491385385478SLisandro Dalcin   *x = snes->vec_sol_update;
49143a40ed3dSBarry Smith   PetscFunctionReturn(0);
49159b94acceSBarry Smith }
49169b94acceSBarry Smith 
49179b94acceSBarry Smith /*@C
4918f6dfbefdSBarry Smith    SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
49199b94acceSBarry Smith 
4920f6dfbefdSBarry Smith    Not Collective, but r is parallel if snes is parallel. Collective if r is requested, but has not been created yet.
4921c7afd0dbSLois Curfman McInnes 
49229b94acceSBarry Smith    Input Parameter:
4923f6dfbefdSBarry Smith .  snes - the `SNES` context
49249b94acceSBarry Smith 
4925d8d19677SJose E. Roman    Output Parameters:
49260298fd71SBarry Smith +  r - the vector that is used to store residuals (or NULL if you don't want it)
4927f6dfbefdSBarry Smith .  f - the function (or NULL if you don't want it); see `SNESFunction` for calling sequence details
49280298fd71SBarry Smith -  ctx - the function context (or NULL if you don't want it)
49299b94acceSBarry Smith 
493036851e7fSLois Curfman McInnes    Level: advanced
493136851e7fSLois Curfman McInnes 
4932f6dfbefdSBarry Smith     Note:
4933f6dfbefdSBarry Smith    The vector r DOES NOT, in general, contain the current value of the `SNES` nonlinear function
493404edfde5SBarry Smith 
4935f6dfbefdSBarry Smith .seealso: `SNES, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction`
49369b94acceSBarry Smith @*/
4937d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4938d71ae5a4SJacob Faibussowitsch {
49396cab3a1bSJed Brown   DM dm;
4940a63bb30eSJed Brown 
49413a40ed3dSBarry Smith   PetscFunctionBegin;
49420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4943a63bb30eSJed Brown   if (r) {
4944a63bb30eSJed Brown     if (!snes->vec_func) {
4945a63bb30eSJed Brown       if (snes->vec_rhs) {
49469566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
4947a63bb30eSJed Brown       } else if (snes->vec_sol) {
49489566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
4949a63bb30eSJed Brown       } else if (snes->dm) {
49509566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
4951a63bb30eSJed Brown       }
4952a63bb30eSJed Brown     }
4953a63bb30eSJed Brown     *r = snes->vec_func;
4954a63bb30eSJed Brown   }
49559566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49569566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
49573a40ed3dSBarry Smith   PetscFunctionReturn(0);
49589b94acceSBarry Smith }
49599b94acceSBarry Smith 
4960c79ef259SPeter Brune /*@C
4961f6dfbefdSBarry Smith    SNESGetNGS - Returns the `SNESNGS` function and context set with `SNESSetNGS()`
4962c79ef259SPeter Brune 
4963c79ef259SPeter Brune    Input Parameter:
4964f6dfbefdSBarry Smith .  snes - the `SNES` context
4965c79ef259SPeter Brune 
4966d8d19677SJose E. Roman    Output Parameters:
4967f6dfbefdSBarry Smith +  f - the function (or NULL) see `SNESNGSFunction` for details
49680298fd71SBarry Smith -  ctx    - the function context (or NULL)
4969c79ef259SPeter Brune 
4970c79ef259SPeter Brune    Level: advanced
4971c79ef259SPeter Brune 
4972db781477SPatrick Sanan .seealso: `SNESSetNGS()`, `SNESGetFunction()`
4973c79ef259SPeter Brune @*/
4974c79ef259SPeter Brune 
4975d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4976d71ae5a4SJacob Faibussowitsch {
49776cab3a1bSJed Brown   DM dm;
49786cab3a1bSJed Brown 
4979646217ecSPeter Brune   PetscFunctionBegin;
4980646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49829566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
4983646217ecSPeter Brune   PetscFunctionReturn(0);
4984646217ecSPeter Brune }
4985646217ecSPeter Brune 
49863c7409f5SSatish Balay /*@C
49873c7409f5SSatish Balay    SNESSetOptionsPrefix - Sets the prefix used for searching for all
4988f6dfbefdSBarry Smith    `SNES` options in the database.
49893c7409f5SSatish Balay 
4990c3339decSBarry Smith    Logically Collective
4991fee21e36SBarry Smith 
4992d8d19677SJose E. Roman    Input Parameters:
4993f6dfbefdSBarry Smith +  snes - the `SNES` context
4994c7afd0dbSLois Curfman McInnes -  prefix - the prefix to prepend to all option names
4995c7afd0dbSLois Curfman McInnes 
4996f6dfbefdSBarry Smith    Note:
4997a83b1b31SSatish Balay    A hyphen (-) must NOT be given at the beginning of the prefix name.
4998c7afd0dbSLois Curfman McInnes    The first character of all runtime options is AUTOMATICALLY the hyphen.
4999d850072dSLois Curfman McInnes 
500036851e7fSLois Curfman McInnes    Level: advanced
500136851e7fSLois Curfman McInnes 
5002f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
50033c7409f5SSatish Balay @*/
5004d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5005d71ae5a4SJacob Faibussowitsch {
50063a40ed3dSBarry Smith   PetscFunctionBegin;
50070700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50089566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
50099566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
501035f5d045SPeter Brune   if (snes->linesearch) {
50119566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50129566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
501335f5d045SPeter Brune   }
50149566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
50153a40ed3dSBarry Smith   PetscFunctionReturn(0);
50163c7409f5SSatish Balay }
50173c7409f5SSatish Balay 
50183c7409f5SSatish Balay /*@C
5019f525115eSLois Curfman McInnes    SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5020f6dfbefdSBarry Smith    `SNES` options in the database.
50213c7409f5SSatish Balay 
5022c3339decSBarry Smith    Logically Collective
5023fee21e36SBarry Smith 
5024c7afd0dbSLois Curfman McInnes    Input Parameters:
5025f6dfbefdSBarry Smith +  snes - the `SNES` context
5026c7afd0dbSLois Curfman McInnes -  prefix - the prefix to prepend to all option names
5027c7afd0dbSLois Curfman McInnes 
5028f6dfbefdSBarry Smith    Note:
5029a83b1b31SSatish Balay    A hyphen (-) must NOT be given at the beginning of the prefix name.
5030c7afd0dbSLois Curfman McInnes    The first character of all runtime options is AUTOMATICALLY the hyphen.
5031d850072dSLois Curfman McInnes 
503236851e7fSLois Curfman McInnes    Level: advanced
503336851e7fSLois Curfman McInnes 
5034f6dfbefdSBarry Smith .seealso: `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
50353c7409f5SSatish Balay @*/
5036d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5037d71ae5a4SJacob Faibussowitsch {
50383a40ed3dSBarry Smith   PetscFunctionBegin;
50390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50409566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
50419566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
504235f5d045SPeter Brune   if (snes->linesearch) {
50439566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50449566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
504535f5d045SPeter Brune   }
50469566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
50473a40ed3dSBarry Smith   PetscFunctionReturn(0);
50483c7409f5SSatish Balay }
50493c7409f5SSatish Balay 
50509ab63eb5SSatish Balay /*@C
5051f6dfbefdSBarry Smith    SNESGetOptionsPrefix - Gets the prefix used for searching for all
5052f6dfbefdSBarry Smith    `SNES` options in the database.
50533c7409f5SSatish Balay 
5054c7afd0dbSLois Curfman McInnes    Not Collective
5055c7afd0dbSLois Curfman McInnes 
50563c7409f5SSatish Balay    Input Parameter:
5057f6dfbefdSBarry Smith .  snes - the `SNES` context
50583c7409f5SSatish Balay 
50593c7409f5SSatish Balay    Output Parameter:
50603c7409f5SSatish Balay .  prefix - pointer to the prefix string used
50613c7409f5SSatish Balay 
5062f6dfbefdSBarry Smith    Fortran Note:
506395452b02SPatrick Sanan     On the fortran side, the user should pass in a string 'prefix' of
50649ab63eb5SSatish Balay    sufficient length to hold the prefix.
50659ab63eb5SSatish Balay 
506636851e7fSLois Curfman McInnes    Level: advanced
506736851e7fSLois Curfman McInnes 
5068f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
50693c7409f5SSatish Balay @*/
5070d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5071d71ae5a4SJacob Faibussowitsch {
50723a40ed3dSBarry Smith   PetscFunctionBegin;
50730700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50749566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
50753a40ed3dSBarry Smith   PetscFunctionReturn(0);
50763c7409f5SSatish Balay }
50773c7409f5SSatish Balay 
50783cea93caSBarry Smith /*@C
50791c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
50801c84c290SBarry Smith 
50811c84c290SBarry Smith    Not collective
50821c84c290SBarry Smith 
50831c84c290SBarry Smith    Input Parameters:
50841c84c290SBarry Smith +  name_solver - name of a new user-defined solver
50851c84c290SBarry Smith -  routine_create - routine to create method context
50861c84c290SBarry Smith 
5087f6dfbefdSBarry Smith    Note:
5088f6dfbefdSBarry Smith    `SNESRegister()` may be called multiple times to add several user-defined solvers.
50891c84c290SBarry Smith 
50901c84c290SBarry Smith    Sample usage:
50911c84c290SBarry Smith .vb
5092bdf89e91SBarry Smith    SNESRegister("my_solver",MySolverCreate);
50931c84c290SBarry Smith .ve
50941c84c290SBarry Smith 
50951c84c290SBarry Smith    Then, your solver can be chosen with the procedural interface via
50961c84c290SBarry Smith $     SNESSetType(snes,"my_solver")
50971c84c290SBarry Smith    or at runtime via the option
50981c84c290SBarry Smith $     -snes_type my_solver
50991c84c290SBarry Smith 
51001c84c290SBarry Smith    Level: advanced
51011c84c290SBarry Smith 
5102db781477SPatrick Sanan .seealso: `SNESRegisterAll()`, `SNESRegisterDestroy()`
51033cea93caSBarry Smith @*/
5104d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5105d71ae5a4SJacob Faibussowitsch {
5106b2002411SLois Curfman McInnes   PetscFunctionBegin;
51079566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
51089566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
5109b2002411SLois Curfman McInnes   PetscFunctionReturn(0);
5110b2002411SLois Curfman McInnes }
5111da9b6338SBarry Smith 
5112d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5113d71ae5a4SJacob Faibussowitsch {
511477431f27SBarry Smith   PetscInt    N, i, j;
5115da9b6338SBarry Smith   Vec         u, uh, fh;
5116da9b6338SBarry Smith   PetscScalar value;
5117da9b6338SBarry Smith   PetscReal   norm;
5118da9b6338SBarry Smith 
5119da9b6338SBarry Smith   PetscFunctionBegin;
51209566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
51219566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
51229566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5123da9b6338SBarry Smith 
5124da9b6338SBarry Smith   /* currently only works for sequential */
51259566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
51269566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5127da9b6338SBarry Smith   for (i = 0; i < N; i++) {
51289566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
512963a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5130da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
51318b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
51329566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
51339566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
51349566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
513563a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5136da9b6338SBarry Smith       value = -value;
51379566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5138da9b6338SBarry Smith     }
5139da9b6338SBarry Smith   }
51409566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
51419566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
5142da9b6338SBarry Smith   PetscFunctionReturn(0);
5143da9b6338SBarry Smith }
514471f87433Sdalcinl 
514571f87433Sdalcinl /*@
5146f6dfbefdSBarry Smith    SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
514771f87433Sdalcinl    computing relative tolerance for linear solvers within an inexact
514871f87433Sdalcinl    Newton method.
514971f87433Sdalcinl 
5150c3339decSBarry Smith    Logically Collective
515171f87433Sdalcinl 
515271f87433Sdalcinl    Input Parameters:
5153f6dfbefdSBarry Smith +  snes - `SNES` context
5154f6dfbefdSBarry Smith -  flag - `PETSC_TRUE` or `PETSC_FALSE`
515571f87433Sdalcinl 
5156f6dfbefdSBarry Smith     Options Database Keys:
515764ba62caSBarry Smith +  -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
515864ba62caSBarry Smith .  -snes_ksp_ew_version ver - version of  Eisenstat-Walker method
515964ba62caSBarry Smith .  -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
516064ba62caSBarry Smith .  -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
516164ba62caSBarry Smith .  -snes_ksp_ew_gamma <gamma> - Sets gamma
516264ba62caSBarry Smith .  -snes_ksp_ew_alpha <alpha> - Sets alpha
516364ba62caSBarry Smith .  -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
516464ba62caSBarry Smith -  -snes_ksp_ew_threshold <threshold> - Sets threshold
516564ba62caSBarry Smith 
5166f6dfbefdSBarry Smith    Note:
5167f6dfbefdSBarry Smith    The default is to use a constant relative tolerance for
516871f87433Sdalcinl    the inner linear solvers.  Alternatively, one can use the
516971f87433Sdalcinl    Eisenstat-Walker method, where the relative convergence tolerance
517071f87433Sdalcinl    is reset at each Newton iteration according progress of the nonlinear
517171f87433Sdalcinl    solver.
517271f87433Sdalcinl 
517371f87433Sdalcinl    Level: advanced
517471f87433Sdalcinl 
517571f87433Sdalcinl    Reference:
5176f6dfbefdSBarry Smith .  - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996.
517771f87433Sdalcinl 
5178f6dfbefdSBarry Smith .seealso: `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
517971f87433Sdalcinl @*/
5180d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5181d71ae5a4SJacob Faibussowitsch {
518271f87433Sdalcinl   PetscFunctionBegin;
51830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5184acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
518571f87433Sdalcinl   snes->ksp_ewconv = flag;
518671f87433Sdalcinl   PetscFunctionReturn(0);
518771f87433Sdalcinl }
518871f87433Sdalcinl 
518971f87433Sdalcinl /*@
5190f6dfbefdSBarry Smith    SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
519171f87433Sdalcinl    for computing relative tolerance for linear solvers within an
519271f87433Sdalcinl    inexact Newton method.
519371f87433Sdalcinl 
519471f87433Sdalcinl    Not Collective
519571f87433Sdalcinl 
519671f87433Sdalcinl    Input Parameter:
5197f6dfbefdSBarry Smith .  snes - `SNES` context
519871f87433Sdalcinl 
519971f87433Sdalcinl    Output Parameter:
5200f6dfbefdSBarry Smith .  flag - `PETSC_TRUE` or `PETSC_FALSE`
520171f87433Sdalcinl 
520271f87433Sdalcinl    Level: advanced
520371f87433Sdalcinl 
5204db781477SPatrick Sanan .seealso: `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
520571f87433Sdalcinl @*/
5206d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5207d71ae5a4SJacob Faibussowitsch {
520871f87433Sdalcinl   PetscFunctionBegin;
52090700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5210534a8f05SLisandro Dalcin   PetscValidBoolPointer(flag, 2);
521171f87433Sdalcinl   *flag = snes->ksp_ewconv;
521271f87433Sdalcinl   PetscFunctionReturn(0);
521371f87433Sdalcinl }
521471f87433Sdalcinl 
521571f87433Sdalcinl /*@
5216fa9f3622SBarry Smith    SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
521771f87433Sdalcinl    convergence criteria for the linear solvers within an inexact
521871f87433Sdalcinl    Newton method.
521971f87433Sdalcinl 
5220c3339decSBarry Smith    Logically Collective
522171f87433Sdalcinl 
522271f87433Sdalcinl    Input Parameters:
5223f6dfbefdSBarry Smith +    snes - `SNES` context
52240f0abf79SStefano Zampini .    version - version 1, 2 (default is 2), 3 or 4
522571f87433Sdalcinl .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
522671f87433Sdalcinl .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
522771f87433Sdalcinl .    gamma - multiplicative factor for version 2 rtol computation
522871f87433Sdalcinl              (0 <= gamma2 <= 1)
522971f87433Sdalcinl .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
523071f87433Sdalcinl .    alpha2 - power for safeguard
523171f87433Sdalcinl -    threshold - threshold for imposing safeguard (0 < threshold < 1)
523271f87433Sdalcinl 
5233f6dfbefdSBarry Smith    Notes:
523471f87433Sdalcinl    Version 3 was contributed by Luis Chacon, June 2006.
523571f87433Sdalcinl 
5236f6dfbefdSBarry Smith    Use `PETSC_DEFAULT` to retain the default for any of the parameters.
523771f87433Sdalcinl 
523871f87433Sdalcinl    Level: advanced
523971f87433Sdalcinl 
5240f6dfbefdSBarry Smith .seealso: `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
524171f87433Sdalcinl @*/
5242d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5243d71ae5a4SJacob Faibussowitsch {
5244fa9f3622SBarry Smith   SNESKSPEW *kctx;
52455fd66863SKarl Rupp 
524671f87433Sdalcinl   PetscFunctionBegin;
52470700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5248fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52495f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5250c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5251c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5252c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5253c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5254c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5255c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5256c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
525771f87433Sdalcinl 
525871f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
525971f87433Sdalcinl   if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
526071f87433Sdalcinl   if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max;
526171f87433Sdalcinl   if (gamma != PETSC_DEFAULT) kctx->gamma = gamma;
526271f87433Sdalcinl   if (alpha != PETSC_DEFAULT) kctx->alpha = alpha;
526371f87433Sdalcinl   if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2;
526471f87433Sdalcinl   if (threshold != PETSC_DEFAULT) kctx->threshold = threshold;
526571f87433Sdalcinl 
52660f0abf79SStefano 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);
52670b121fc5SBarry 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);
52680b121fc5SBarry 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);
52690b121fc5SBarry 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);
52700b121fc5SBarry 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);
52710b121fc5SBarry 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);
527271f87433Sdalcinl   PetscFunctionReturn(0);
527371f87433Sdalcinl }
527471f87433Sdalcinl 
527571f87433Sdalcinl /*@
5276fa9f3622SBarry Smith    SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
527771f87433Sdalcinl    convergence criteria for the linear solvers within an inexact
527871f87433Sdalcinl    Newton method.
527971f87433Sdalcinl 
528071f87433Sdalcinl    Not Collective
528171f87433Sdalcinl 
528297bb3fdcSJose E. Roman    Input Parameter:
5283f6dfbefdSBarry Smith .    snes - `SNES` context
528471f87433Sdalcinl 
528571f87433Sdalcinl    Output Parameters:
52860f0abf79SStefano Zampini +    version - version 1, 2 (default is 2), 3 or 4
528771f87433Sdalcinl .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
528871f87433Sdalcinl .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
5289bf388a1fSBarry Smith .    gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
529071f87433Sdalcinl .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
529171f87433Sdalcinl .    alpha2 - power for safeguard
529271f87433Sdalcinl -    threshold - threshold for imposing safeguard (0 < threshold < 1)
529371f87433Sdalcinl 
529471f87433Sdalcinl    Level: advanced
529571f87433Sdalcinl 
5296f6dfbefdSBarry Smith .seealso: `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
529771f87433Sdalcinl @*/
5298d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5299d71ae5a4SJacob Faibussowitsch {
5300fa9f3622SBarry Smith   SNESKSPEW *kctx;
53015fd66863SKarl Rupp 
530271f87433Sdalcinl   PetscFunctionBegin;
53030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5304fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53055f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
530671f87433Sdalcinl   if (version) *version = kctx->version;
530771f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
530871f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
530971f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
531071f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
531171f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
531271f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
531371f87433Sdalcinl   PetscFunctionReturn(0);
531471f87433Sdalcinl }
531571f87433Sdalcinl 
5316d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5317d71ae5a4SJacob Faibussowitsch {
5318fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
531971f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
532071f87433Sdalcinl 
532171f87433Sdalcinl   PetscFunctionBegin;
5322d4211eb9SBarry Smith   if (!snes->ksp_ewconv) PetscFunctionReturn(0);
532330058271SDmitry Karpeev   if (!snes->iter) {
532430058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
53259566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
53260f0abf79SStefano Zampini   } else {
532771f87433Sdalcinl     if (kctx->version == 1) {
53280f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
532985ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
533071f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
533171f87433Sdalcinl     } else if (kctx->version == 2) {
533285ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
533385ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
533471f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
533571f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
533685ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
533771f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
533885ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
533971f87433Sdalcinl       stol = PetscMax(rtol, stol);
534071f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
534171f87433Sdalcinl       /* safeguard: avoid oversolving */
534230058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
534371f87433Sdalcinl       stol = PetscMax(rtol, stol);
534471f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
53450f0abf79SStefano Zampini     } else if (kctx->version == 4) { /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
53460f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
53470f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
53480f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
53490f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
53500f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
53510f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
53520f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
53530f0abf79SStefano Zampini 
53549371c9d4SSatish Balay       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) {
53550f0abf79SStefano Zampini         rtol = kctx->v4_m4 * kctx->rtol_last;
53560f0abf79SStefano Zampini         //printf("iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g (rk %g ps %g %g %g) (AD)\n",snes->iter,kctx->version,(double)rtol,rk,kctx->v4_p1,kctx->v4_p2,kctx->v4_p3);
53570f0abf79SStefano Zampini       } else {
53580f0abf79SStefano Zampini         //printf("iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g (rk %g ps %g %g %g)\n",snes->iter,kctx->version,(double)rtol,rk,kctx->v4_p1,kctx->v4_p2,kctx->v4_p3);
535971f87433Sdalcinl       }
53600f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
53610f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
53620f0abf79SStefano Zampini       kctx->rk_last     = rk;
53630f0abf79SStefano Zampini     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version);
53640f0abf79SStefano Zampini   }
53650f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
536671f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
53679566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
536863a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
536971f87433Sdalcinl   PetscFunctionReturn(0);
537071f87433Sdalcinl }
537171f87433Sdalcinl 
5372d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5373d71ae5a4SJacob Faibussowitsch {
5374fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
537571f87433Sdalcinl   PCSide     pcside;
537671f87433Sdalcinl   Vec        lres;
537771f87433Sdalcinl 
537871f87433Sdalcinl   PetscFunctionBegin;
5379d4211eb9SBarry Smith   if (!snes->ksp_ewconv) PetscFunctionReturn(0);
53809566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
538171dbe336SPeter Brune   kctx->norm_last = snes->norm;
53820f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
53834f00ce20SMatthew G. Knepley     PC        pc;
53840f0abf79SStefano Zampini     PetscBool getRes;
53854f00ce20SMatthew G. Knepley 
53869566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
53870f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
53880f0abf79SStefano Zampini     if (!getRes) {
53890f0abf79SStefano Zampini       KSPNormType normtype;
53900f0abf79SStefano Zampini 
53910f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
53920f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
53930f0abf79SStefano Zampini     }
53949566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
53950f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
53969566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
539771f87433Sdalcinl     } else {
539871f87433Sdalcinl       /* KSP residual is preconditioned residual */
539971f87433Sdalcinl       /* compute true linear residual norm */
54000f0abf79SStefano Zampini       Mat J;
54010f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
54029566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
54030f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
54049566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
54059566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
54069566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
540771f87433Sdalcinl     }
540871f87433Sdalcinl   }
540971f87433Sdalcinl   PetscFunctionReturn(0);
541071f87433Sdalcinl }
541171f87433Sdalcinl 
5412d4211eb9SBarry Smith /*@
5413f6dfbefdSBarry Smith    SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5414d4211eb9SBarry Smith 
5415f6dfbefdSBarry Smith    Not Collective, but if snes is parallel, then ksp is parallel
5416d4211eb9SBarry Smith 
5417d4211eb9SBarry Smith    Input Parameter:
5418f6dfbefdSBarry Smith .  snes - the `SNES` context
5419d4211eb9SBarry Smith 
5420d4211eb9SBarry Smith    Output Parameter:
5421f6dfbefdSBarry Smith .  ksp - the `KSP` context
5422d4211eb9SBarry Smith 
5423d4211eb9SBarry Smith    Notes:
5424f6dfbefdSBarry Smith    The user can then directly manipulate the `KSP` context to set various
5425d4211eb9SBarry Smith    options, etc.  Likewise, the user can then extract and manipulate the
5426f6dfbefdSBarry Smith    `PC` contexts as well.
5427f6dfbefdSBarry Smith 
5428f6dfbefdSBarry Smith    Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5429d4211eb9SBarry Smith 
5430d4211eb9SBarry Smith    Level: beginner
5431d4211eb9SBarry Smith 
5432f6dfbefdSBarry Smith .seealso: `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5433d4211eb9SBarry Smith @*/
5434d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5435d71ae5a4SJacob Faibussowitsch {
543671f87433Sdalcinl   PetscFunctionBegin;
5437d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5438d4211eb9SBarry Smith   PetscValidPointer(ksp, 2);
5439d4211eb9SBarry Smith 
5440d4211eb9SBarry Smith   if (!snes->ksp) {
54419566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
54429566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5443d4211eb9SBarry Smith 
54449566063dSJacob Faibussowitsch     PetscCall(KSPSetPreSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_SNESEW, snes));
54459566063dSJacob Faibussowitsch     PetscCall(KSPSetPostSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_SNESEW, snes));
5446a5c2985bSBarry Smith 
54479566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
54489566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5449d4211eb9SBarry Smith   }
5450d4211eb9SBarry Smith   *ksp = snes->ksp;
545171f87433Sdalcinl   PetscFunctionReturn(0);
545271f87433Sdalcinl }
54536c699258SBarry Smith 
5454af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
54556c699258SBarry Smith /*@
5456f6dfbefdSBarry Smith    SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
54576c699258SBarry Smith 
5458c3339decSBarry Smith    Logically Collective
54596c699258SBarry Smith 
54606c699258SBarry Smith    Input Parameters:
54612a808120SBarry Smith +  snes - the nonlinear solver context
54622a808120SBarry Smith -  dm - the dm, cannot be NULL
54636c699258SBarry Smith 
5464f6dfbefdSBarry Smith    Note:
5465f6dfbefdSBarry Smith    A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5466f6dfbefdSBarry Smith    even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5467e03a659cSJed Brown    problems using the same function space.
5468e03a659cSJed Brown 
54696c699258SBarry Smith    Level: intermediate
54706c699258SBarry Smith 
5471f6dfbefdSBarry Smith .seealso: `DM`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
54726c699258SBarry Smith @*/
5473d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5474d71ae5a4SJacob Faibussowitsch {
5475345fed2cSBarry Smith   KSP    ksp;
5476942e3340SBarry Smith   DMSNES sdm;
54776c699258SBarry Smith 
54786c699258SBarry Smith   PetscFunctionBegin;
54790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54802a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
54819566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5482942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
548351f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
54849566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
54859566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5486f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
54876cab3a1bSJed Brown     }
54889566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
54899566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
54906cab3a1bSJed Brown   }
54916c699258SBarry Smith   snes->dm     = dm;
5492116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5493f5af7f23SKarl Rupp 
54949566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
54959566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
54969566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5497efd4aadfSBarry Smith   if (snes->npc) {
54989566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
54999566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
55002c155ee1SBarry Smith   }
55016c699258SBarry Smith   PetscFunctionReturn(0);
55026c699258SBarry Smith }
55036c699258SBarry Smith 
55046c699258SBarry Smith /*@
5505f6dfbefdSBarry Smith    SNESGetDM - Gets the `DM` that may be used by some preconditioners
55066c699258SBarry Smith 
5507f6dfbefdSBarry Smith    Not Collective but dm obtained is parallel on snes
55086c699258SBarry Smith 
55096c699258SBarry Smith    Input Parameter:
55106c699258SBarry Smith . snes - the preconditioner context
55116c699258SBarry Smith 
55126c699258SBarry Smith    Output Parameter:
55136c699258SBarry Smith .  dm - the dm
55146c699258SBarry Smith 
55156c699258SBarry Smith    Level: intermediate
55166c699258SBarry Smith 
5517f6dfbefdSBarry Smith .seealso: `DM`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
55186c699258SBarry Smith @*/
5519d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5520d71ae5a4SJacob Faibussowitsch {
55216c699258SBarry Smith   PetscFunctionBegin;
55220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55236cab3a1bSJed Brown   if (!snes->dm) {
55249566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5525116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
55266cab3a1bSJed Brown   }
55276c699258SBarry Smith   *dm = snes->dm;
55286c699258SBarry Smith   PetscFunctionReturn(0);
55296c699258SBarry Smith }
55300807856dSBarry Smith 
553131823bd8SMatthew G Knepley /*@
5532be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
553331823bd8SMatthew G Knepley 
5534c3339decSBarry Smith   Collective
553531823bd8SMatthew G Knepley 
553631823bd8SMatthew G Knepley   Input Parameters:
5537f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5538f6dfbefdSBarry Smith - npc   - the preconditioner object
553931823bd8SMatthew G Knepley 
554031823bd8SMatthew G Knepley   Notes:
5541f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
554231823bd8SMatthew G Knepley   to configure it using the API).
554331823bd8SMatthew G Knepley 
5544f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5545f6dfbefdSBarry Smith 
554631823bd8SMatthew G Knepley   Level: developer
554731823bd8SMatthew G Knepley 
5548f6dfbefdSBarry Smith .seealso: `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
554931823bd8SMatthew G Knepley @*/
5550d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5551d71ae5a4SJacob Faibussowitsch {
555231823bd8SMatthew G Knepley   PetscFunctionBegin;
555331823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5554f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5555f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5556f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
55579566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5558f6dfbefdSBarry Smith   snes->npc = npc;
555931823bd8SMatthew G Knepley   PetscFunctionReturn(0);
556031823bd8SMatthew G Knepley }
556131823bd8SMatthew G Knepley 
556231823bd8SMatthew G Knepley /*@
5563f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
556431823bd8SMatthew G Knepley 
5565f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
556631823bd8SMatthew G Knepley 
556731823bd8SMatthew G Knepley   Input Parameter:
5568f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
556931823bd8SMatthew G Knepley 
557031823bd8SMatthew G Knepley   Output Parameter:
5571f6dfbefdSBarry Smith . npc - preconditioner context
557231823bd8SMatthew G Knepley 
5573f6dfbefdSBarry Smith   Options Database Key:
5574f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5575b5badacbSBarry Smith 
557695452b02SPatrick Sanan   Notes:
5577f6dfbefdSBarry Smith     If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5578be95d8f1SBarry Smith 
5579f6dfbefdSBarry Smith     The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5580f6dfbefdSBarry Smith     `SNES`
5581951fe5abSBarry Smith 
558231823bd8SMatthew G Knepley   Level: developer
558331823bd8SMatthew G Knepley 
5584db781477SPatrick Sanan .seealso: `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
558531823bd8SMatthew G Knepley @*/
5586d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5587d71ae5a4SJacob Faibussowitsch {
5588a64e098fSPeter Brune   const char *optionsprefix;
558931823bd8SMatthew G Knepley 
559031823bd8SMatthew G Knepley   PetscFunctionBegin;
559131823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
559231823bd8SMatthew G Knepley   PetscValidPointer(pc, 2);
5593efd4aadfSBarry Smith   if (!snes->npc) {
55949566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
55959566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
55969566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
55979566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
55989566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
55999566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
560031823bd8SMatthew G Knepley   }
5601efd4aadfSBarry Smith   *pc = snes->npc;
560231823bd8SMatthew G Knepley   PetscFunctionReturn(0);
560331823bd8SMatthew G Knepley }
560431823bd8SMatthew G Knepley 
56053ad1a0b9SPatrick Farrell /*@
56063ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
56073ad1a0b9SPatrick Farrell 
56083ad1a0b9SPatrick Farrell   Not Collective
56093ad1a0b9SPatrick Farrell 
56103ad1a0b9SPatrick Farrell   Input Parameter:
5611f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56123ad1a0b9SPatrick Farrell 
56133ad1a0b9SPatrick Farrell   Output Parameter:
5614f6dfbefdSBarry Smith . has_npc - whether the `SNES` has an NPC or not
56153ad1a0b9SPatrick Farrell 
56163ad1a0b9SPatrick Farrell   Level: developer
56173ad1a0b9SPatrick Farrell 
5618db781477SPatrick Sanan .seealso: `SNESSetNPC()`, `SNESGetNPC()`
56193ad1a0b9SPatrick Farrell @*/
5620d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5621d71ae5a4SJacob Faibussowitsch {
56223ad1a0b9SPatrick Farrell   PetscFunctionBegin;
56233ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5624efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
56253ad1a0b9SPatrick Farrell   PetscFunctionReturn(0);
56263ad1a0b9SPatrick Farrell }
56273ad1a0b9SPatrick Farrell 
5628c40d0f55SPeter Brune /*@
5629be95d8f1SBarry Smith     SNESSetNPCSide - Sets the preconditioning side.
5630c40d0f55SPeter Brune 
5631c3339decSBarry Smith     Logically Collective
5632c40d0f55SPeter Brune 
5633c40d0f55SPeter Brune     Input Parameter:
5634f6dfbefdSBarry Smith .   snes - iterative context obtained from `SNESCreate()`
5635c40d0f55SPeter Brune 
5636c40d0f55SPeter Brune     Output Parameter:
5637c40d0f55SPeter Brune .   side - the preconditioning side, where side is one of
5638c40d0f55SPeter Brune .vb
56392d547940SBarry Smith       PC_LEFT - left preconditioning
56402d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5641c40d0f55SPeter Brune .ve
5642c40d0f55SPeter Brune 
5643f6dfbefdSBarry Smith     Options Database Key:
564467b8a455SSatish Balay .   -snes_npc_side <right,left> - nonlinear preconditioner side
5645c40d0f55SPeter Brune 
5646f6dfbefdSBarry Smith     Note:
5647f6dfbefdSBarry Smith     `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
56482d547940SBarry Smith 
5649c40d0f55SPeter Brune     Level: intermediate
5650c40d0f55SPeter Brune 
5651f6dfbefdSBarry Smith .seealso: `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`
5652c40d0f55SPeter Brune @*/
5653d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5654d71ae5a4SJacob Faibussowitsch {
5655c40d0f55SPeter Brune   PetscFunctionBegin;
5656c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5657c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5658b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
565954c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5660efd4aadfSBarry Smith   snes->npcside = side;
5661c40d0f55SPeter Brune   PetscFunctionReturn(0);
5662c40d0f55SPeter Brune }
5663c40d0f55SPeter Brune 
5664c40d0f55SPeter Brune /*@
5665be95d8f1SBarry Smith     SNESGetNPCSide - Gets the preconditioning side.
5666c40d0f55SPeter Brune 
5667c40d0f55SPeter Brune     Not Collective
5668c40d0f55SPeter Brune 
5669c40d0f55SPeter Brune     Input Parameter:
5670f6dfbefdSBarry Smith .   snes - iterative context obtained from `SNESCreate()`
5671c40d0f55SPeter Brune 
5672c40d0f55SPeter Brune     Output Parameter:
5673c40d0f55SPeter Brune .   side - the preconditioning side, where side is one of
5674c40d0f55SPeter Brune .vb
5675f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5676f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5677c40d0f55SPeter Brune .ve
5678c40d0f55SPeter Brune 
5679c40d0f55SPeter Brune     Level: intermediate
5680c40d0f55SPeter Brune 
5681f6dfbefdSBarry Smith .seealso: `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`
5682c40d0f55SPeter Brune @*/
5683d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5684d71ae5a4SJacob Faibussowitsch {
5685c40d0f55SPeter Brune   PetscFunctionBegin;
5686c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5687c40d0f55SPeter Brune   PetscValidPointer(side, 2);
5688efd4aadfSBarry Smith   *side = snes->npcside;
5689c40d0f55SPeter Brune   PetscFunctionReturn(0);
5690c40d0f55SPeter Brune }
5691c40d0f55SPeter Brune 
56929e764e56SPeter Brune /*@
5693f6dfbefdSBarry Smith   SNESSetLineSearch - Sets the linesearch on the `SNES` instance.
56949e764e56SPeter Brune 
5695c3339decSBarry Smith   Collective
56969e764e56SPeter Brune 
56979e764e56SPeter Brune   Input Parameters:
5698f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
56999e764e56SPeter Brune - linesearch   - the linesearch object
57009e764e56SPeter Brune 
5701f6dfbefdSBarry Smith   Note:
5702f6dfbefdSBarry Smith   Use `SNESGetLineSearch()` to retrieve the preconditioner context (for example,
57039e764e56SPeter Brune   to configure it using the API).
57049e764e56SPeter Brune 
57059e764e56SPeter Brune   Level: developer
57069e764e56SPeter Brune 
5707db781477SPatrick Sanan .seealso: `SNESGetLineSearch()`
57089e764e56SPeter Brune @*/
5709d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5710d71ae5a4SJacob Faibussowitsch {
57119e764e56SPeter Brune   PetscFunctionBegin;
57129e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5713f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
57149e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
57159566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
57169566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5717f5af7f23SKarl Rupp 
57189e764e56SPeter Brune   snes->linesearch = linesearch;
5719f5af7f23SKarl Rupp 
57209e764e56SPeter Brune   PetscFunctionReturn(0);
57219e764e56SPeter Brune }
57229e764e56SPeter Brune 
5723a34ceb2aSJed Brown /*@
5724f6dfbefdSBarry Smith   SNESGetLineSearch - Returns a pointer to the line search context set with `SNESSetLineSearch()`
5725f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
57269e764e56SPeter Brune 
57279e764e56SPeter Brune   Not Collective
57289e764e56SPeter Brune 
57299e764e56SPeter Brune   Input Parameter:
5730f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57319e764e56SPeter Brune 
57329e764e56SPeter Brune   Output Parameter:
57339e764e56SPeter Brune . linesearch - linesearch context
57349e764e56SPeter Brune 
5735162e0bf5SPeter Brune   Level: beginner
57369e764e56SPeter Brune 
5737f6dfbefdSBarry Smith .seealso: `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
57389e764e56SPeter Brune @*/
5739d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5740d71ae5a4SJacob Faibussowitsch {
57419e764e56SPeter Brune   const char *optionsprefix;
57429e764e56SPeter Brune 
57439e764e56SPeter Brune   PetscFunctionBegin;
57449e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57459e764e56SPeter Brune   PetscValidPointer(linesearch, 2);
57469e764e56SPeter Brune   if (!snes->linesearch) {
57479566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57489566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
57499566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
57509566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
57519566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
57529e764e56SPeter Brune   }
57539e764e56SPeter Brune   *linesearch = snes->linesearch;
57549e764e56SPeter Brune   PetscFunctionReturn(0);
57559e764e56SPeter Brune }
5756