xref: /petsc/src/snes/interface/snes.c (revision 20f4b53cbb5e9bd9ef12b76a8697d60d197cda17)
1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h"  I*/
207475bc1SBarry Smith #include <petscdmshell.h>
3d96771aaSLisandro Dalcin #include <petscdraw.h>
4a01aa210SMatthew G. Knepley #include <petscds.h>
534b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h>
606fc46c8SMatthew G. Knepley #include <petscconvest.h>
79b94acceSBarry Smith 
8ace3abfcSBarry Smith PetscBool         SNESRegisterAllCalled = PETSC_FALSE;
90298fd71SBarry Smith PetscFunctionList SNESList              = NULL;
108ba1e511SMatthew Knepley 
118ba1e511SMatthew Knepley /* Logging support */
1222c6f798SBarry Smith PetscClassId  SNES_CLASSID, DMSNES_CLASSID;
13fc8bc0e3SRichard Tran Mills PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval;
14a09944afSBarry Smith 
15e113a28aSBarry Smith /*@
16dc4c0fb0SBarry Smith    SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged.
17e113a28aSBarry Smith 
18c3339decSBarry Smith    Logically Collective
19e113a28aSBarry Smith 
20e113a28aSBarry Smith    Input Parameters:
21f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
22f6dfbefdSBarry Smith -  flg - `PETSC_TRUE` indicates you want the error generated
23e113a28aSBarry Smith 
24*20f4b53cSBarry Smith    Options Database Key:
2567b8a455SSatish Balay .  -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge
26e113a28aSBarry Smith 
27e113a28aSBarry Smith    Level: intermediate
28e113a28aSBarry Smith 
29f6dfbefdSBarry Smith    Note:
30f6dfbefdSBarry Smith    Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()`
31f6dfbefdSBarry Smith    to determine if it has converged. Otherwise the solution may be inaccurate or wrong
32e113a28aSBarry Smith 
33dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
34e113a28aSBarry Smith @*/
35d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg)
36d71ae5a4SJacob Faibussowitsch {
37e113a28aSBarry Smith   PetscFunctionBegin;
38e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flg, 2);
40e113a28aSBarry Smith   snes->errorifnotconverged = flg;
413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42e113a28aSBarry Smith }
43e113a28aSBarry Smith 
44e113a28aSBarry Smith /*@
45f6dfbefdSBarry Smith    SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge?
46e113a28aSBarry Smith 
47e113a28aSBarry Smith    Not Collective
48e113a28aSBarry Smith 
49e113a28aSBarry Smith    Input Parameter:
50f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
51e113a28aSBarry Smith 
52e113a28aSBarry Smith    Output Parameter:
53f6dfbefdSBarry Smith .  flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE`
54e113a28aSBarry Smith 
55e113a28aSBarry Smith    Level: intermediate
56e113a28aSBarry Smith 
57dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
58e113a28aSBarry Smith @*/
59d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag)
60d71ae5a4SJacob Faibussowitsch {
61e113a28aSBarry Smith   PetscFunctionBegin;
62e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
63534a8f05SLisandro Dalcin   PetscValidBoolPointer(flag, 2);
64e113a28aSBarry Smith   *flag = snes->errorifnotconverged;
653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66e113a28aSBarry Smith }
67e113a28aSBarry Smith 
684fc747eaSLawrence Mitchell /*@
69dc4c0fb0SBarry Smith     SNESSetAlwaysComputesFinalResidual - tells the `SNES` to always compute the residual (nonlinear function value) at the final solution
704fc747eaSLawrence Mitchell 
71c3339decSBarry Smith    Logically Collective
724fc747eaSLawrence Mitchell 
734fc747eaSLawrence Mitchell     Input Parameters:
74f6dfbefdSBarry Smith +   snes - the shell `SNES`
75f6dfbefdSBarry Smith -   flg - `PETSC_TRUE` to always compute the residual
764fc747eaSLawrence Mitchell 
774fc747eaSLawrence Mitchell    Level: advanced
784fc747eaSLawrence Mitchell 
79f6dfbefdSBarry Smith    Note:
80f6dfbefdSBarry Smith    Some solvers (such as smoothers in a `SNESFAS`) do not need the residual computed at the final solution so skip computing it
81f6dfbefdSBarry Smith    to save time.
82f6dfbefdSBarry Smith 
83dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESGetAlwaysComputesFinalResidual()`
844fc747eaSLawrence Mitchell @*/
85d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg)
86d71ae5a4SJacob Faibussowitsch {
874fc747eaSLawrence Mitchell   PetscFunctionBegin;
884fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
894fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = flg;
903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
914fc747eaSLawrence Mitchell }
924fc747eaSLawrence Mitchell 
934fc747eaSLawrence Mitchell /*@
94f6dfbefdSBarry Smith     SNESGetAlwaysComputesFinalResidual - checks if the `SNES` always computes the residual at the final solution
954fc747eaSLawrence Mitchell 
96c3339decSBarry Smith    Logically Collective
974fc747eaSLawrence Mitchell 
984fc747eaSLawrence Mitchell     Input Parameter:
99f6dfbefdSBarry Smith .   snes - the `SNES` context
1004fc747eaSLawrence Mitchell 
1014fc747eaSLawrence Mitchell     Output Parameter:
102f6dfbefdSBarry Smith .   flg - `PETSC_TRUE` if the residual is computed
1034fc747eaSLawrence Mitchell 
1044fc747eaSLawrence Mitchell    Level: advanced
1054fc747eaSLawrence Mitchell 
106dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()`
1074fc747eaSLawrence Mitchell @*/
108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg)
109d71ae5a4SJacob Faibussowitsch {
1104fc747eaSLawrence Mitchell   PetscFunctionBegin;
1114fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1124fc747eaSLawrence Mitchell   *flg = snes->alwayscomputesfinalresidual;
1133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1144fc747eaSLawrence Mitchell }
1154fc747eaSLawrence Mitchell 
116e725d27bSBarry Smith /*@
117f6dfbefdSBarry Smith    SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not
118f0b84518SBarry Smith      in the functions domain. For example, a step with negative pressure.
1194936397dSBarry Smith 
120c3339decSBarry Smith    Logically Collective
1214936397dSBarry Smith 
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 
131dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `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;
1403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
157dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `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;
1663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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:
176*20f4b53cSBarry Smith +  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 
184dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESConvergedReason`, `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;
1913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
207dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `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;
2153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
231dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `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;
2393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
255dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `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;
2633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
281dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `PetscViewer`, `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));
3083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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
317dc4c0fb0SBarry Smith    SNESViewFromOptions - View a `SNES` based on values in the options database
318fe2efc57SMark 
319c3339decSBarry Smith    Collective
320fe2efc57SMark 
321fe2efc57SMark    Input Parameters:
322f6dfbefdSBarry Smith +  A - the `SNES` context
323dc4c0fb0SBarry Smith .  obj - Optional object that provides the options prefix for the checks
324736c3998SJose E. Roman -  name - command line option
325fe2efc57SMark 
326fe2efc57SMark    Level: intermediate
327f6dfbefdSBarry Smith 
328dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `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));
3353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
336fe2efc57SMark }
337fe2efc57SMark 
338789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
339789d8953SBarry Smith 
3407e2c5f70SBarry Smith /*@C
341dc4c0fb0SBarry Smith    SNESView - Prints or visualizes 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 
352dc4c0fb0SBarry Smith    Level: beginner
353dc4c0fb0SBarry Smith 
3549b94acceSBarry Smith    Notes:
3559b94acceSBarry Smith    The available visualization contexts include
356f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
357f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
358c8a8ba5cSLois Curfman McInnes          output where only the first processor opens
359c8a8ba5cSLois Curfman McInnes          the file.  All other processors send their
360c8a8ba5cSLois Curfman McInnes          data to the first processor to print.
3619b94acceSBarry Smith 
362052bf0daSPierre Jolivet    The available formats include
363f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
364f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
365052bf0daSPierre Jolivet 
3663e081fefSLois Curfman McInnes    The user can open an alternative visualization context with
367f6dfbefdSBarry Smith    `PetscViewerASCIIOpen()` - output to a specified file.
3689b94acceSBarry Smith 
369f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
370595c91d4SBarry Smith 
371dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `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   }
5353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
556dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `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;
5633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
5790fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
580aa3661deSLisandro Dalcin   if (version == 1) {
5819566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5829566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5839566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5841e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
5850fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
5865f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
587570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
588f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
589aa3661deSLisandro Dalcin #else
5902479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
591aa3661deSLisandro Dalcin #endif
5920fdf79fbSJacob Faibussowitsch   }
593aa3661deSLisandro Dalcin 
594895c21f2SBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix free matrix */
595895c21f2SBarry Smith   if (snes->jacobian) {
5969566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
5971baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
598895c21f2SBarry Smith   }
599895c21f2SBarry Smith 
60063a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
601d3462f78SMatthew Knepley   if (hasOperator) {
602aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
603aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6049566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
605aa3661deSLisandro Dalcin   } else {
606aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
6073232da50SPeter Brune      provided preconditioner Jacobian with the default matrix free version. */
608b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6099566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
610172a4300SPeter Brune     } else {
611789d8953SBarry Smith       KSP       ksp;
612789d8953SBarry Smith       PC        pc;
613789d8953SBarry Smith       PetscBool match;
614789d8953SBarry Smith 
6159566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
616aa3661deSLisandro Dalcin       /* Force no preconditioner */
6179566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6189566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6192698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
620aa3661deSLisandro Dalcin       if (!match) {
6219566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6229566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
623aa3661deSLisandro Dalcin       }
624aa3661deSLisandro Dalcin     }
625789d8953SBarry Smith   }
6269566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
628aa3661deSLisandro Dalcin }
629aa3661deSLisandro Dalcin 
630d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
631d71ae5a4SJacob Faibussowitsch {
632dfe15315SJed Brown   SNES snes = (SNES)ctx;
6330298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
634dfe15315SJed Brown 
635dfe15315SJed Brown   PetscFunctionBegin;
63616ebb321SJed Brown   if (PetscLogPrintInfo) {
63716ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6389566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6399566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6409566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6419566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
64263a3b9bcSJacob 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));
64316ebb321SJed Brown   }
644dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
645dfe15315SJed Brown   else {
6469566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
647dfe15315SJed Brown     Xfine = Xfine_named;
648dfe15315SJed Brown   }
6499566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
650907f5c5aSLawrence Mitchell   if (Inject) {
6519566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
652907f5c5aSLawrence Mitchell   } else {
6539566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6549566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
655907f5c5aSLawrence Mitchell   }
6569566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6579566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
659dfe15315SJed Brown }
660dfe15315SJed Brown 
661d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
662d71ae5a4SJacob Faibussowitsch {
66316ebb321SJed Brown   PetscFunctionBegin;
6649566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66616ebb321SJed Brown }
66716ebb321SJed Brown 
668a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
669a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
670d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
671d71ae5a4SJacob Faibussowitsch {
672caa4e7f2SJed Brown   SNES  snes = (SNES)ctx;
6730298fd71SBarry Smith   Vec   X, Xnamed = NULL;
674dfe15315SJed Brown   DM    dmsave;
6754e269d77SPeter Brune   void *ctxsave;
67625ce1634SJed Brown   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = NULL;
677caa4e7f2SJed Brown 
678caa4e7f2SJed Brown   PetscFunctionBegin;
679dfe15315SJed Brown   dmsave = snes->dm;
6809566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
681dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
6829371c9d4SSatish Balay   else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */ PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
683dfe15315SJed Brown     X = Xnamed;
6849566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
6854e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
68648a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
6874e269d77SPeter Brune   }
6884dde8bb0SMatthew G. Knepley   /* Make sure KSP DM has the Jacobian computation routine */
6894dde8bb0SMatthew G. Knepley   {
6904dde8bb0SMatthew G. Knepley     DMSNES sdm;
6914e269d77SPeter Brune 
6929566063dSJacob Faibussowitsch     PetscCall(DMGetDMSNES(snes->dm, &sdm));
69348a46eb9SPierre Jolivet     if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
6944dde8bb0SMatthew G. Knepley   }
6952b93b426SMatthew G. Knepley   /* Compute the operators */
6969566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
6972b93b426SMatthew G. Knepley   /* Put the previous context back */
69848a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
6994e269d77SPeter Brune 
7009566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
701dfe15315SJed Brown   snes->dm = dmsave;
7023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
703caa4e7f2SJed Brown }
704caa4e7f2SJed Brown 
7056cab3a1bSJed Brown /*@
706dc4c0fb0SBarry Smith    SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7076cab3a1bSJed Brown 
7086cab3a1bSJed Brown    Collective
7096cab3a1bSJed Brown 
7104165533cSJose E. Roman    Input Parameter:
711*20f4b53cSBarry Smith .  snes - `SNES` object to configure
7126cab3a1bSJed Brown 
7136cab3a1bSJed Brown    Level: developer
7146cab3a1bSJed Brown 
715dc4c0fb0SBarry Smith    Note:
716dc4c0fb0SBarry Smith    If the matrices do not yet exist it attempts to create them based on options previously set for the `SNES` such as `-snes_mf`
717dc4c0fb0SBarry Smith 
718dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetUp()`
7196cab3a1bSJed Brown @*/
720d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
721d71ae5a4SJacob Faibussowitsch {
7226cab3a1bSJed Brown   DM     dm;
723942e3340SBarry Smith   DMSNES sdm;
7246cab3a1bSJed Brown 
7256cab3a1bSJed Brown   PetscFunctionBegin;
7269566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7279566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
72858b371f3SBarry Smith   if (!snes->jacobian && snes->mf) {
7296cab3a1bSJed Brown     Mat   J;
7306cab3a1bSJed Brown     void *functx;
7319566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7329566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7339566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7349566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7359566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7369566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
737caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7386cab3a1bSJed Brown     Mat J, B;
7399566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7409566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7419566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7429566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
74306f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7449566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7459566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
747caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7481ba9b98eSMatthew G. Knepley     PetscDS   prob;
7496cab3a1bSJed Brown     Mat       J, B;
7501ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7511ba9b98eSMatthew G. Knepley 
7526cab3a1bSJed Brown     J = snes->jacobian;
7539566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7549566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7559566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7569566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7579566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7589566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7599566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7609566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7616cab3a1bSJed Brown   }
762caa4e7f2SJed Brown   {
763caa4e7f2SJed Brown     KSP ksp;
7649566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
7659566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
7669566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
767caa4e7f2SJed Brown   }
7683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7696cab3a1bSJed Brown }
7706cab3a1bSJed Brown 
771d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
772d71ae5a4SJacob Faibussowitsch {
7735e7c47f3SMatthew G. Knepley   PetscInt i;
7745e7c47f3SMatthew G. Knepley 
7755e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
7763ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
7775e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
7785e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
7795e7c47f3SMatthew G. Knepley     PetscDraw             draw;
7805e7c47f3SMatthew G. Knepley     PetscReal             lpause;
7815e7c47f3SMatthew G. Knepley 
7825e7c47f3SMatthew G. Knepley     if (!vf) continue;
7835e7c47f3SMatthew G. Knepley     if (vf->lg) {
7845e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
7855e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
7869566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
7879566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
7889566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
7899566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
7909566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
7915e7c47f3SMatthew G. Knepley     } else {
7925e7c47f3SMatthew G. Knepley       PetscBool isdraw;
7935e7c47f3SMatthew G. Knepley 
7945e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
7955e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
7969566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
7975e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
7989566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
7999566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8009566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8019566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8029566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8035e7c47f3SMatthew G. Knepley     }
8045e7c47f3SMatthew G. Knepley   }
8053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8065e7c47f3SMatthew G. Knepley }
8075e7c47f3SMatthew G. Knepley 
808fde5950dSBarry Smith /*@C
809fde5950dSBarry Smith    SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
810fde5950dSBarry Smith 
811c3339decSBarry Smith    Collective
812fde5950dSBarry Smith 
813fde5950dSBarry Smith    Input Parameters:
814dc4c0fb0SBarry Smith +  snes - `SNES` object you wish to monitor
815fde5950dSBarry Smith .  name - the monitor type one is seeking
816fde5950dSBarry Smith .  help - message indicating what monitoring is done
817fde5950dSBarry Smith .  manual - manual page for the monitor
818fde5950dSBarry Smith .  monitor - the monitor function
819f6dfbefdSBarry 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
820fde5950dSBarry Smith 
821f6dfbefdSBarry Smith    Options Database Key:
822f6dfbefdSBarry Smith .  -name - trigger the use of this monitor in `SNESSetFromOptions()`
823f6dfbefdSBarry Smith 
824f6dfbefdSBarry Smith    Level: advanced
825fde5950dSBarry Smith 
826dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
827db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
828db781477SPatrick Sanan           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
829db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
830c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
831db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
832db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
833fde5950dSBarry Smith @*/
834d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSetFromOptions(SNES snes, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNES, PetscInt, PetscReal, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(SNES, PetscViewerAndFormat *))
835d71ae5a4SJacob Faibussowitsch {
836fde5950dSBarry Smith   PetscViewer       viewer;
837fde5950dSBarry Smith   PetscViewerFormat format;
838fde5950dSBarry Smith   PetscBool         flg;
839fde5950dSBarry Smith 
840fde5950dSBarry Smith   PetscFunctionBegin;
8419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
842fde5950dSBarry Smith   if (flg) {
843d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8449566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
8459566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
8461baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8479566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
848fde5950dSBarry Smith   }
8493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
850fde5950dSBarry Smith }
851fde5950dSBarry Smith 
852d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, MPI_Comm comm, const char *prefix)
853d71ae5a4SJacob Faibussowitsch {
8540f0abf79SStefano Zampini   PetscFunctionBegin;
8550f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
8560f0abf79SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", NULL, kctx->version, &kctx->version, NULL));
8570f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", NULL, kctx->rtol_0, &kctx->rtol_0, NULL));
8580f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", NULL, kctx->rtol_max, &kctx->rtol_max, NULL));
8590f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", NULL, kctx->gamma, &kctx->gamma, NULL));
8600f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", NULL, kctx->alpha, &kctx->alpha, NULL));
8610f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
8620f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", NULL, kctx->threshold, &kctx->threshold, NULL));
8630f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8640f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8650f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8660f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8670f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8680f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8690f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8700f0abf79SStefano Zampini   PetscOptionsEnd();
8713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8720f0abf79SStefano Zampini }
8730f0abf79SStefano Zampini 
8749b94acceSBarry Smith /*@
875f6dfbefdSBarry Smith    SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
8769b94acceSBarry Smith 
877c3339decSBarry Smith    Collective
878c7afd0dbSLois Curfman McInnes 
8799b94acceSBarry Smith    Input Parameter:
880f6dfbefdSBarry Smith .  snes - the `SNES` context
8819b94acceSBarry Smith 
88236851e7fSLois Curfman McInnes    Options Database Keys:
883f6dfbefdSBarry Smith +  -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
88482738288SBarry Smith .  -snes_stol - convergence tolerance in terms of the norm
88582738288SBarry Smith                 of the change in the solution between steps
88670441072SBarry Smith .  -snes_atol <abstol> - absolute tolerance of residual norm
887b39c3a46SLois Curfman McInnes .  -snes_rtol <rtol> - relative decrease in tolerance norm from initial
888e4d06f11SPatrick Farrell .  -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
889be5caee7SBarry Smith .  -snes_force_iteration <force> - force SNESSolve() to take at least one iteration
890b39c3a46SLois Curfman McInnes .  -snes_max_it <max_it> - maximum number of iterations
891b39c3a46SLois Curfman McInnes .  -snes_max_funcs <max_funcs> - maximum number of function evaluations
8924839bfe8SBarry Smith .  -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
893ddf469c8SBarry Smith .  -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
894a8054027SBarry Smith .  -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild)
8953d5a8a6aSBarry Smith .  -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve()
896e35cf81dSBarry Smith .  -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild)
8973d5a8a6aSBarry Smith .  -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve()
8984a221d59SStefano Zampini .  -snes_tr_tol <trtol> - trust region tolerance
899f362779dSJed Brown .  -snes_convergence_test - <default,skip,correct_pressure> convergence test in nonlinear solver.
900f6dfbefdSBarry Smith                                default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense
901f6dfbefdSBarry Smith                                of convergence test. correct_pressure S`NESConvergedCorrectPressure()` has special handling of a pressure null space.
902fde5950dSBarry Smith .  -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout
903fde5950dSBarry Smith .  -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
904fde5950dSBarry Smith .  -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration
905fde5950dSBarry Smith .  -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9064619e776SBarry Smith .  -snes_monitor_lg_residualnorm - plots residual norm at each iteration
907459f5d12SBarry Smith .  -snes_monitor_lg_range - plots residual norm at each iteration
9085e7c47f3SMatthew G. Knepley .  -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends
909e24b481bSBarry Smith .  -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
910e2e60de9SPeter Brune .  -snes_fd_color - use finite differences with coloring to compute Jacobian
9115968eb51SBarry Smith .  -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration
912b5badacbSBarry Smith .  -snes_converged_reason - print the reason for convergence/divergence after each solve
913e62ac41dSBarry Smith .  -npc_snes_type <type> - the SNES type to use as a nonlinear preconditioner
914e62ac41dSBarry 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.
915e62ac41dSBarry 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.
91682738288SBarry Smith 
917f6dfbefdSBarry Smith     Options Database Keys for Eisenstat-Walker method:
918fa9f3622SBarry Smith +  -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
9194b27c08aSLois Curfman McInnes .  -snes_ksp_ew_version ver - version of  Eisenstat-Walker method
92036851e7fSLois Curfman McInnes .  -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
92136851e7fSLois Curfman McInnes .  -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
92236851e7fSLois Curfman McInnes .  -snes_ksp_ew_gamma <gamma> - Sets gamma
92336851e7fSLois Curfman McInnes .  -snes_ksp_ew_alpha <alpha> - Sets alpha
92436851e7fSLois Curfman McInnes .  -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
92536851e7fSLois Curfman McInnes -  -snes_ksp_ew_threshold <threshold> - Sets threshold
92682738288SBarry Smith 
927dc4c0fb0SBarry Smith    Level: beginner
928dc4c0fb0SBarry Smith 
92911ca99fdSLois Curfman McInnes    Notes:
930ec5066bdSBarry Smith    To see all options, run your program with the -help option or consult the users manual
931ec5066bdSBarry Smith 
932f6dfbefdSBarry Smith    `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix free, and computing explicitly with
933f6dfbefdSBarry Smith    finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
93483e2fdc7SBarry Smith 
935dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`
9369b94acceSBarry Smith @*/
937d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
938d71ae5a4SJacob Faibussowitsch {
9398afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
940d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
94104d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
942649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
94385385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9440f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
945c40d0f55SPeter Brune   PCSide      pcside;
946a64e098fSPeter Brune   const char *optionsprefix;
9479b94acceSBarry Smith 
9483a40ed3dSBarry Smith   PetscFunctionBegin;
9490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9509566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
951d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
952639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
954d64ed03dSBarry Smith   if (flg) {
9559566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9567adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9579566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
958d64ed03dSBarry Smith   }
9599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
9609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
961186905e3SBarry Smith 
9629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
9639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
9649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
9659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
9669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
9679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
9689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
9699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
9709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
97185385478SLisandro Dalcin 
9729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
973a8054027SBarry Smith   if (flg) {
9745f80ce2aSJacob 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");
9759566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
976a8054027SBarry Smith   }
9779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
9781baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
9799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
980e35cf81dSBarry Smith   if (flg) {
9815f80ce2aSJacob 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");
9829566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
983e35cf81dSBarry Smith   }
9849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
9851baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
98637ec4e1aSPeter Brune 
9879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
9881baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
989a8054027SBarry Smith 
9909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, sizeof(convtests) / sizeof(char *), "default", &indx, &flg));
99185385478SLisandro Dalcin   if (flg) {
99285385478SLisandro Dalcin     switch (indx) {
993d71ae5a4SJacob Faibussowitsch     case 0:
994d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
995d71ae5a4SJacob Faibussowitsch       break;
996d71ae5a4SJacob Faibussowitsch     case 1:
997d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
998d71ae5a4SJacob Faibussowitsch       break;
999d71ae5a4SJacob Faibussowitsch     case 2:
1000d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1001d71ae5a4SJacob Faibussowitsch       break;
100285385478SLisandro Dalcin     }
100385385478SLisandro Dalcin   }
100485385478SLisandro Dalcin 
10059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10069566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1007fdacfa88SPeter Brune 
10089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10099566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1010186905e3SBarry Smith 
101185385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
101285385478SLisandro Dalcin 
10139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1014186905e3SBarry Smith 
10150f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10160f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
10170f0abf79SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PetscObjectComm((PetscObject)snes), ewprefix));
10180f0abf79SStefano Zampini 
10199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_ksp_ew_version", "Version 1, 2 or 3", "SNESKSPSetParametersEW", kctx->version, &kctx->version, NULL));
10209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_rtol0", "0 <= rtol0 < 1", "SNESKSPSetParametersEW", kctx->rtol_0, &kctx->rtol_0, NULL));
10219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_rtolmax", "0 <= rtolmax < 1", "SNESKSPSetParametersEW", kctx->rtol_max, &kctx->rtol_max, NULL));
10229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_gamma", "0 <= gamma <= 1", "SNESKSPSetParametersEW", kctx->gamma, &kctx->gamma, NULL));
10239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_alpha", "1 < alpha <= 2", "SNESKSPSetParametersEW", kctx->alpha, &kctx->alpha, NULL));
10249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_alpha2", "alpha2", "SNESKSPSetParametersEW", kctx->alpha2, &kctx->alpha2, NULL));
10259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_ksp_ew_threshold", "0 < threshold < 1", "SNESKSPSetParametersEW", kctx->threshold, &kctx->threshold, NULL));
1026186905e3SBarry Smith 
102790d69ab7SBarry Smith   flg = PETSC_FALSE;
10289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10299566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1030eabae89aSBarry Smith 
10319566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10329566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10339566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1034eabae89aSBarry Smith 
10359566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10369566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10379566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10389566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10399566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10409566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10419566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10432db13446SMatthew G. Knepley 
10449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10459566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10465180491cSLisandro Dalcin 
104790d69ab7SBarry Smith   flg = PETSC_FALSE;
10489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1049459f5d12SBarry Smith   if (flg) {
1050459f5d12SBarry Smith     PetscViewer ctx;
1051e24b481bSBarry Smith 
10529566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10539566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1054459f5d12SBarry Smith   }
10552e7541e6SPeter Brune 
105690d69ab7SBarry Smith   flg = PETSC_FALSE;
10579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10589566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1059c4421ceaSFande Kong 
1060c4421ceaSFande Kong   flg = PETSC_FALSE;
10619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10624b27c08aSLois Curfman McInnes   if (flg) {
10636cab3a1bSJed Brown     void *functx;
1064b1f624c7SBarry Smith     DM    dm;
10659566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1066800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10679566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10689566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10699566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
10709b94acceSBarry Smith   }
1071639f9d9dSBarry Smith 
107244848bc4SPeter Brune   flg = PETSC_FALSE;
10739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
10741baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
107597584545SPeter Brune 
107697584545SPeter Brune   flg = PETSC_FALSE;
10779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
107844848bc4SPeter Brune   if (flg) {
1079c52e227fSPeter Brune     DM dm;
10809566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1081800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10829566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
10839566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
108444848bc4SPeter Brune   }
108544848bc4SPeter Brune 
1086aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1088d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1089a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1090d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1091a8248277SBarry Smith   }
1092aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1094d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
10959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1096d28543b3SPeter Brune 
1097c40d0f55SPeter Brune   flg = PETSC_FALSE;
10989566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
10999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11009566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1101c40d0f55SPeter Brune 
1102e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11038a70d858SHong Zhang   /*
11048a70d858SHong Zhang     Publish convergence information using SAWs
11058a70d858SHong Zhang   */
11068a70d858SHong Zhang   flg = PETSC_FALSE;
11079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11088a70d858SHong Zhang   if (flg) {
11098a70d858SHong Zhang     void *ctx;
11109566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11119566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11128a70d858SHong Zhang   }
11138a70d858SHong Zhang #endif
11148a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1115b90c6cbeSBarry Smith   {
1116b90c6cbeSBarry Smith     PetscBool set;
1117b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11189566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11191baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1120b90c6cbeSBarry Smith   }
1121b90c6cbeSBarry Smith #endif
1122b90c6cbeSBarry Smith 
112348a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
112476b2cf59SMatthew Knepley 
1125dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11265d973c19SBarry Smith 
11275d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1128dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1129d0609cedSBarry Smith   PetscOptionsEnd();
11304bbc92c1SBarry Smith 
1131d8d34be6SBarry Smith   if (snes->linesearch) {
11329566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11339566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1134d8d34be6SBarry Smith   }
11359e764e56SPeter Brune 
11366aa5e7e9SBarry Smith   if (snes->usesksp) {
11379566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11389566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11399566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11406aa5e7e9SBarry Smith   }
11416991f827SBarry Smith 
1142b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11439566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
114548a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11461baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1147b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1149b3cd9a81SMatthew G. Knepley }
1150b3cd9a81SMatthew G. Knepley 
1151b3cd9a81SMatthew G. Knepley /*@
1152f6dfbefdSBarry Smith    SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously set from options
1153b3cd9a81SMatthew G. Knepley 
1154c3339decSBarry Smith    Collective
1155b3cd9a81SMatthew G. Knepley 
1156b3cd9a81SMatthew G. Knepley    Input Parameter:
1157f6dfbefdSBarry Smith .  snes - the `SNES` context
1158b3cd9a81SMatthew G. Knepley 
1159b3cd9a81SMatthew G. Knepley    Level: beginner
1160b3cd9a81SMatthew G. Knepley 
1161dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1162b3cd9a81SMatthew G. Knepley @*/
1163d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1164d71ae5a4SJacob Faibussowitsch {
1165b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11669566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11689b94acceSBarry Smith }
11699b94acceSBarry Smith 
1170bb9467b5SJed Brown /*@C
1171d25893d9SBarry Smith    SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1172d25893d9SBarry Smith    the nonlinear solvers.
1173d25893d9SBarry Smith 
1174dc4c0fb0SBarry Smith    Logically Collective; No Fortran Support
1175d25893d9SBarry Smith 
1176d25893d9SBarry Smith    Input Parameters:
1177f6dfbefdSBarry Smith +  snes - the `SNES` context
1178d25893d9SBarry Smith .  compute - function to compute the context
1179d25893d9SBarry Smith -  destroy - function to destroy the context
1180d25893d9SBarry Smith 
1181d25893d9SBarry Smith    Level: intermediate
1182d25893d9SBarry Smith 
1183f6dfbefdSBarry Smith    Note:
1184f6dfbefdSBarry Smith    This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1185f6dfbefdSBarry Smith 
1186f6dfbefdSBarry Smith    Use `SNESSetApplicationContext()` to see the context immediately
1187f6dfbefdSBarry Smith 
1188dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetApplicationContext()`, `SNESSetComputeApplicationContext()`, `SNESSetApplicationContext()`
1189d25893d9SBarry Smith @*/
1190d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES, void **), PetscErrorCode (*destroy)(void **))
1191d71ae5a4SJacob Faibussowitsch {
1192d25893d9SBarry Smith   PetscFunctionBegin;
1193d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1194d25893d9SBarry Smith   snes->ops->usercompute = compute;
1195d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
11963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1197d25893d9SBarry Smith }
1198a847f771SSatish Balay 
1199b07ff414SBarry Smith /*@
1200f6dfbefdSBarry Smith    SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12019b94acceSBarry Smith 
1202c3339decSBarry Smith    Logically Collective
1203fee21e36SBarry Smith 
1204c7afd0dbSLois Curfman McInnes    Input Parameters:
1205f6dfbefdSBarry Smith +  snes - the `SNES` context
1206c7afd0dbSLois Curfman McInnes -  usrP - optional user context
1207c7afd0dbSLois Curfman McInnes 
120836851e7fSLois Curfman McInnes    Level: intermediate
120936851e7fSLois Curfman McInnes 
1210f6dfbefdSBarry Smith    Notes:
1211f6dfbefdSBarry Smith    Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1212f6dfbefdSBarry Smith    with `SNESGetApplicationContext()`
1213f6dfbefdSBarry Smith 
1214f6dfbefdSBarry Smith    To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1215f6dfbefdSBarry Smith 
1216f6dfbefdSBarry Smith    Fortran Note:
1217dc4c0fb0SBarry Smith     You must write a Fortran interface definition for this
1218daf670e6SBarry Smith     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1219daf670e6SBarry Smith 
1220dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12219b94acceSBarry Smith @*/
1222d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1223d71ae5a4SJacob Faibussowitsch {
1224b07ff414SBarry Smith   KSP ksp;
12251b2093e4SBarry Smith 
12263a40ed3dSBarry Smith   PetscFunctionBegin;
12270700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12289566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12299566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12309b94acceSBarry Smith   snes->user = usrP;
12313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12329b94acceSBarry Smith }
123374679c65SBarry Smith 
1234b07ff414SBarry Smith /*@
12359b94acceSBarry Smith    SNESGetApplicationContext - Gets the user-defined context for the
1236f6dfbefdSBarry Smith    nonlinear solvers set with `SNESGetApplicationContext()` or with `SNESSetComputeApplicationContext()`
12379b94acceSBarry Smith 
1238c7afd0dbSLois Curfman McInnes    Not Collective
1239c7afd0dbSLois Curfman McInnes 
12409b94acceSBarry Smith    Input Parameter:
1241f6dfbefdSBarry Smith .  snes - `SNES` context
12429b94acceSBarry Smith 
12439b94acceSBarry Smith    Output Parameter:
12449b94acceSBarry Smith .  usrP - user context
12459b94acceSBarry Smith 
124636851e7fSLois Curfman McInnes    Level: intermediate
124736851e7fSLois Curfman McInnes 
1248dc4c0fb0SBarry Smith    Fortran Note:
1249dc4c0fb0SBarry Smith    You must write a Fortran interface definition for this
1250dc4c0fb0SBarry Smith    function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1251dc4c0fb0SBarry Smith 
1252dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetApplicationContext()`
12539b94acceSBarry Smith @*/
1254d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1255d71ae5a4SJacob Faibussowitsch {
12563a40ed3dSBarry Smith   PetscFunctionBegin;
12570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1258e71120c6SJed Brown   *(void **)usrP = snes->user;
12593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12609b94acceSBarry Smith }
126174679c65SBarry Smith 
12629b94acceSBarry Smith /*@
1263f6dfbefdSBarry Smith    SNESSetUseMatrixFree - indicates that `SNES` should use matrix free finite difference matrix vector products to apply the Jacobian.
12643565c898SBarry Smith 
1265dc4c0fb0SBarry Smith    Logically Collective
12663565c898SBarry Smith 
12673565c898SBarry Smith    Input Parameters:
1268f6dfbefdSBarry Smith +  snes - `SNES` context
1269f6dfbefdSBarry Smith .  mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1270f6dfbefdSBarry Smith -  mf - use matrix-free for both the Amat and Pmat used by `SNESSetJacobian()`, both the Amat and Pmat set in `SNESSetJacobian()` will be ignored. With
1271f6dfbefdSBarry Smith    this option no matrix element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
12723565c898SBarry Smith 
1273f6dfbefdSBarry Smith    Options Database Keys:
1274f6dfbefdSBarry Smith + -snes_mf_operator - use matrix free only for the mat operator
1275f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator
1276ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences.
1277ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow)
12783565c898SBarry Smith 
12793565c898SBarry Smith    Level: intermediate
12803565c898SBarry Smith 
1281f6dfbefdSBarry Smith    Note:
1282dc4c0fb0SBarry Smith    `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free, and computing explicitly with
1283f6dfbefdSBarry Smith    finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1284ec5066bdSBarry Smith 
1285dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`
12863565c898SBarry Smith @*/
1287d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1288d71ae5a4SJacob Faibussowitsch {
12893565c898SBarry Smith   PetscFunctionBegin;
12903565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
129188b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
129288b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
12934ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
12943565c898SBarry Smith   snes->mf_operator = mf_operator;
12953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12963565c898SBarry Smith }
12973565c898SBarry Smith 
12983565c898SBarry Smith /*@
1299dc4c0fb0SBarry Smith    SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13003565c898SBarry Smith 
1301f6dfbefdSBarry Smith    Not Collective, but the resulting flags will be the same on all MPI ranks
13023565c898SBarry Smith 
13033565c898SBarry Smith    Input Parameter:
1304f6dfbefdSBarry Smith .  snes - `SNES` context
13053565c898SBarry Smith 
13063565c898SBarry Smith    Output Parameters:
1307f6dfbefdSBarry Smith +  mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1308f6dfbefdSBarry Smith -  mf - use matrix-free for both the Amat and Pmat used by `SNESSetJacobian()`, both the Amat and Pmat set in `SNESSetJacobian()` will be ignored
13093565c898SBarry Smith 
13103565c898SBarry Smith    Level: intermediate
13113565c898SBarry Smith 
1312dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13133565c898SBarry Smith @*/
1314d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1315d71ae5a4SJacob Faibussowitsch {
13163565c898SBarry Smith   PetscFunctionBegin;
13173565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13183565c898SBarry Smith   if (mf) *mf = snes->mf;
13193565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13213565c898SBarry Smith }
13223565c898SBarry Smith 
13233565c898SBarry Smith /*@
1324c8228a4eSBarry Smith    SNESGetIterationNumber - Gets the number of nonlinear iterations completed
1325c8228a4eSBarry Smith    at this time.
13269b94acceSBarry Smith 
1327c7afd0dbSLois Curfman McInnes    Not Collective
1328c7afd0dbSLois Curfman McInnes 
13299b94acceSBarry Smith    Input Parameter:
1330f6dfbefdSBarry Smith .  snes - `SNES` context
13319b94acceSBarry Smith 
13329b94acceSBarry Smith    Output Parameter:
13339b94acceSBarry Smith .  iter - iteration number
13349b94acceSBarry Smith 
1335dc4c0fb0SBarry Smith    Level: intermediate
1336dc4c0fb0SBarry Smith 
1337c8228a4eSBarry Smith    Notes:
1338c8228a4eSBarry Smith    For example, during the computation of iteration 2 this would return 1.
1339c8228a4eSBarry Smith 
1340c8228a4eSBarry Smith    This is useful for using lagged Jacobians (where one does not recompute the
1341f6dfbefdSBarry Smith    Jacobian at each `SNES` iteration). For example, the code
134208405cd6SLois Curfman McInnes .vb
134308405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
134408405cd6SLois Curfman McInnes       if (!(it % 2)) {
134508405cd6SLois Curfman McInnes         [compute Jacobian here]
134608405cd6SLois Curfman McInnes       }
134708405cd6SLois Curfman McInnes .ve
1348f6dfbefdSBarry Smith    can be used in your function that computes the Jacobian to cause the Jacobian to be
1349f6dfbefdSBarry Smith    recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1350c8228a4eSBarry Smith 
1351f6dfbefdSBarry Smith    After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1352c04deec6SBarry Smith 
1353dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`
13549b94acceSBarry Smith @*/
1355d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1356d71ae5a4SJacob Faibussowitsch {
13573a40ed3dSBarry Smith   PetscFunctionBegin;
13580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13594482741eSBarry Smith   PetscValidIntPointer(iter, 2);
13609b94acceSBarry Smith   *iter = snes->iter;
13613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13629b94acceSBarry Smith }
136374679c65SBarry Smith 
1364360c497dSPeter Brune /*@
1365360c497dSPeter Brune    SNESSetIterationNumber - Sets the current iteration number.
1366360c497dSPeter Brune 
1367360c497dSPeter Brune    Not Collective
1368360c497dSPeter Brune 
1369d8d19677SJose E. Roman    Input Parameters:
1370f6dfbefdSBarry Smith +  snes - `SNES` context
1371a2b725a8SWilliam Gropp -  iter - iteration number
1372360c497dSPeter Brune 
1373360c497dSPeter Brune    Level: developer
1374360c497dSPeter Brune 
1375dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetLinearSolveIterations()`
1376360c497dSPeter Brune @*/
1377d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1378d71ae5a4SJacob Faibussowitsch {
1379360c497dSPeter Brune   PetscFunctionBegin;
1380360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1382360c497dSPeter Brune   snes->iter = iter;
13839566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
13843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1385360c497dSPeter Brune }
1386360c497dSPeter Brune 
13879b94acceSBarry Smith /*@
1388b850b91aSLisandro Dalcin    SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
13899b94acceSBarry Smith    attempted by the nonlinear solver.
13909b94acceSBarry Smith 
1391c7afd0dbSLois Curfman McInnes    Not Collective
1392c7afd0dbSLois Curfman McInnes 
13939b94acceSBarry Smith    Input Parameter:
1394f6dfbefdSBarry Smith .  snes - `SNES` context
13959b94acceSBarry Smith 
13969b94acceSBarry Smith    Output Parameter:
13979b94acceSBarry Smith .  nfails - number of unsuccessful steps attempted
13989b94acceSBarry Smith 
1399dc4c0fb0SBarry Smith    Level: intermediate
1400dc4c0fb0SBarry Smith 
1401f6dfbefdSBarry Smith    Note:
1402f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()`.
1403c96a6f78SLois Curfman McInnes 
1404dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1405db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14069b94acceSBarry Smith @*/
1407d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1408d71ae5a4SJacob Faibussowitsch {
14093a40ed3dSBarry Smith   PetscFunctionBegin;
14100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14114482741eSBarry Smith   PetscValidIntPointer(nfails, 2);
141250ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
141450ffb88aSMatthew Knepley }
141550ffb88aSMatthew Knepley 
141650ffb88aSMatthew Knepley /*@
1417b850b91aSLisandro Dalcin    SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1418f6dfbefdSBarry Smith    attempted by the nonlinear solver before it gives up and generates an error
141950ffb88aSMatthew Knepley 
142050ffb88aSMatthew Knepley    Not Collective
142150ffb88aSMatthew Knepley 
142250ffb88aSMatthew Knepley    Input Parameters:
1423f6dfbefdSBarry Smith +  snes     - `SNES` context
142450ffb88aSMatthew Knepley -  maxFails - maximum of unsuccessful steps
142550ffb88aSMatthew Knepley 
142650ffb88aSMatthew Knepley    Level: intermediate
142750ffb88aSMatthew Knepley 
1428dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1429db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
143050ffb88aSMatthew Knepley @*/
1431d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1432d71ae5a4SJacob Faibussowitsch {
143350ffb88aSMatthew Knepley   PetscFunctionBegin;
14340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
143550ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
14363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143750ffb88aSMatthew Knepley }
143850ffb88aSMatthew Knepley 
143950ffb88aSMatthew Knepley /*@
1440b850b91aSLisandro Dalcin    SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1441f6dfbefdSBarry Smith    attempted by the nonlinear solver before it gives up and generates an error
144250ffb88aSMatthew Knepley 
144350ffb88aSMatthew Knepley    Not Collective
144450ffb88aSMatthew Knepley 
144550ffb88aSMatthew Knepley    Input Parameter:
1446*20f4b53cSBarry Smith .  snes     - `SNES` context
144750ffb88aSMatthew Knepley 
144850ffb88aSMatthew Knepley    Output Parameter:
144950ffb88aSMatthew Knepley .  maxFails - maximum of unsuccessful steps
145050ffb88aSMatthew Knepley 
145150ffb88aSMatthew Knepley    Level: intermediate
145250ffb88aSMatthew Knepley 
1453dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1454db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
145550ffb88aSMatthew Knepley @*/
1456d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1457d71ae5a4SJacob Faibussowitsch {
145850ffb88aSMatthew Knepley   PetscFunctionBegin;
14590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14604482741eSBarry Smith   PetscValidIntPointer(maxFails, 2);
146150ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
14623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14639b94acceSBarry Smith }
1464a847f771SSatish Balay 
14652541af92SBarry Smith /*@
14662541af92SBarry Smith    SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1467f6dfbefdSBarry Smith      done by the `SNES` object
14682541af92SBarry Smith 
14692541af92SBarry Smith    Not Collective
14702541af92SBarry Smith 
14712541af92SBarry Smith    Input Parameter:
1472f6dfbefdSBarry Smith .  snes     - `SNES` context
14732541af92SBarry Smith 
14742541af92SBarry Smith    Output Parameter:
14752541af92SBarry Smith .  nfuncs - number of evaluations
14762541af92SBarry Smith 
14772541af92SBarry Smith    Level: intermediate
14782541af92SBarry Smith 
1479f6dfbefdSBarry Smith    Note:
1480f6dfbefdSBarry Smith     Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1481971e163fSPeter Brune 
1482dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
14832541af92SBarry Smith @*/
1484d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1485d71ae5a4SJacob Faibussowitsch {
14862541af92SBarry Smith   PetscFunctionBegin;
14870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14882541af92SBarry Smith   PetscValidIntPointer(nfuncs, 2);
14892541af92SBarry Smith   *nfuncs = snes->nfuncs;
14903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14912541af92SBarry Smith }
14922541af92SBarry Smith 
14933d4c4710SBarry Smith /*@
14943d4c4710SBarry Smith    SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
14953d4c4710SBarry Smith    linear solvers.
14963d4c4710SBarry Smith 
14973d4c4710SBarry Smith    Not Collective
14983d4c4710SBarry Smith 
14993d4c4710SBarry Smith    Input Parameter:
1500f6dfbefdSBarry Smith .  snes - `SNES` context
15013d4c4710SBarry Smith 
15023d4c4710SBarry Smith    Output Parameter:
15033d4c4710SBarry Smith .  nfails - number of failed solves
15043d4c4710SBarry Smith 
1505f6dfbefdSBarry Smith    Options Database Key:
15069d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15079d85da0cSMatthew G. Knepley 
1508f6dfbefdSBarry Smith    Level: intermediate
1509f6dfbefdSBarry Smith 
1510f6dfbefdSBarry Smith    Note:
1511f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()`.
15123d4c4710SBarry Smith 
1513dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15143d4c4710SBarry Smith @*/
1515d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1516d71ae5a4SJacob Faibussowitsch {
15173d4c4710SBarry Smith   PetscFunctionBegin;
15180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15193d4c4710SBarry Smith   PetscValidIntPointer(nfails, 2);
15203d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15223d4c4710SBarry Smith }
15233d4c4710SBarry Smith 
15243d4c4710SBarry Smith /*@
15253d4c4710SBarry Smith    SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1526f6dfbefdSBarry Smith    allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15273d4c4710SBarry Smith 
1528c3339decSBarry Smith    Logically Collective
15293d4c4710SBarry Smith 
15303d4c4710SBarry Smith    Input Parameters:
1531f6dfbefdSBarry Smith +  snes     - `SNES` context
15323d4c4710SBarry Smith -  maxFails - maximum allowed linear solve failures
15333d4c4710SBarry Smith 
1534f6dfbefdSBarry Smith    Options Database Key:
15359d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15369d85da0cSMatthew G. Knepley 
1537dc4c0fb0SBarry Smith    Level: intermediate
1538dc4c0fb0SBarry Smith 
1539f6dfbefdSBarry Smith    Note:
1540f6dfbefdSBarry Smith     By default this is 0; that is `SNES` returns on the first failed linear solve
15413d4c4710SBarry Smith 
1542dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
15433d4c4710SBarry Smith @*/
1544d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1545d71ae5a4SJacob Faibussowitsch {
15463d4c4710SBarry Smith   PetscFunctionBegin;
15470700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1548c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
15493d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
15503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15513d4c4710SBarry Smith }
15523d4c4710SBarry Smith 
15533d4c4710SBarry Smith /*@
15543d4c4710SBarry Smith    SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1555f6dfbefdSBarry Smith      are allowed before `SNES` returns as unsuccessful
15563d4c4710SBarry Smith 
15573d4c4710SBarry Smith    Not Collective
15583d4c4710SBarry Smith 
15593d4c4710SBarry Smith    Input Parameter:
1560f6dfbefdSBarry Smith .  snes     - `SNES` context
15613d4c4710SBarry Smith 
15623d4c4710SBarry Smith    Output Parameter:
15633d4c4710SBarry Smith .  maxFails - maximum of unsuccessful solves allowed
15643d4c4710SBarry Smith 
15653d4c4710SBarry Smith    Level: intermediate
15663d4c4710SBarry Smith 
1567f6dfbefdSBarry Smith    Note:
1568f6dfbefdSBarry Smith     By default this is 1; that is `SNES` returns on the first failed linear solve
15693d4c4710SBarry Smith 
1570dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
15713d4c4710SBarry Smith @*/
1572d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1573d71ae5a4SJacob Faibussowitsch {
15743d4c4710SBarry Smith   PetscFunctionBegin;
15750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15763d4c4710SBarry Smith   PetscValidIntPointer(maxFails, 2);
15773d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
15783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15793d4c4710SBarry Smith }
15803d4c4710SBarry Smith 
1581c96a6f78SLois Curfman McInnes /*@
1582b850b91aSLisandro Dalcin    SNESGetLinearSolveIterations - Gets the total number of linear iterations
1583c96a6f78SLois Curfman McInnes    used by the nonlinear solver.
1584c96a6f78SLois Curfman McInnes 
1585c7afd0dbSLois Curfman McInnes    Not Collective
1586c7afd0dbSLois Curfman McInnes 
1587c96a6f78SLois Curfman McInnes    Input Parameter:
1588f6dfbefdSBarry Smith .  snes - `SNES` context
1589c96a6f78SLois Curfman McInnes 
1590c96a6f78SLois Curfman McInnes    Output Parameter:
1591c96a6f78SLois Curfman McInnes .  lits - number of linear iterations
1592c96a6f78SLois Curfman McInnes 
1593dc4c0fb0SBarry Smith    Level: intermediate
1594dc4c0fb0SBarry Smith 
1595c96a6f78SLois Curfman McInnes    Notes:
1596f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1597c96a6f78SLois Curfman McInnes 
1598f6dfbefdSBarry Smith    If the linear solver fails inside the `SNESSolve()` the iterations for that call to the linear solver are not included. If you wish to count them
1599f6dfbefdSBarry Smith    then call `KSPGetIterationNumber()` after the failed solve.
1600010be392SBarry Smith 
1601dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1602c96a6f78SLois Curfman McInnes @*/
1603d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1604d71ae5a4SJacob Faibussowitsch {
16053a40ed3dSBarry Smith   PetscFunctionBegin;
16060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16074482741eSBarry Smith   PetscValidIntPointer(lits, 2);
1608c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1610c96a6f78SLois Curfman McInnes }
1611c96a6f78SLois Curfman McInnes 
1612971e163fSPeter Brune /*@
1613971e163fSPeter Brune    SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1614f6dfbefdSBarry Smith    are reset every time `SNESSolve()` is called.
1615971e163fSPeter Brune 
1616c3339decSBarry Smith    Logically Collective
1617971e163fSPeter Brune 
1618d8d19677SJose E. Roman    Input Parameters:
1619f6dfbefdSBarry Smith +  snes - `SNES` context
1620f6dfbefdSBarry Smith -  reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1621971e163fSPeter Brune 
1622971e163fSPeter Brune    Level: developer
1623971e163fSPeter Brune 
1624dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1625971e163fSPeter Brune @*/
1626d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1627d71ae5a4SJacob Faibussowitsch {
1628971e163fSPeter Brune   PetscFunctionBegin;
1629971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1630971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1631971e163fSPeter Brune   snes->counters_reset = reset;
16323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1633971e163fSPeter Brune }
1634971e163fSPeter Brune 
16352999313aSBarry Smith /*@
1636f6dfbefdSBarry Smith    SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16372999313aSBarry Smith 
1638f6dfbefdSBarry Smith    Not Collective, but the `SNES` and `KSP` objects must live on the same MPI_Comm
16392999313aSBarry Smith 
16402999313aSBarry Smith    Input Parameters:
1641f6dfbefdSBarry Smith +  snes - the `SNES` context
1642f6dfbefdSBarry Smith -  ksp - the `KSP` context
16432999313aSBarry Smith 
1644dc4c0fb0SBarry Smith    Level: developer
1645dc4c0fb0SBarry Smith 
16462999313aSBarry Smith    Notes:
1647f6dfbefdSBarry Smith    The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
16482999313aSBarry Smith    so this routine is rarely needed.
16492999313aSBarry Smith 
1650f6dfbefdSBarry Smith    The `KSP` object that is already in the `SNES` object has its reference count
16512999313aSBarry Smith    decreased by one.
16522999313aSBarry Smith 
1653dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
16542999313aSBarry Smith @*/
1655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1656d71ae5a4SJacob Faibussowitsch {
16572999313aSBarry Smith   PetscFunctionBegin;
16580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16590700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
16602999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
16619566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
16629566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
16632999313aSBarry Smith   snes->ksp = ksp;
16643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16652999313aSBarry Smith }
16662999313aSBarry Smith 
166752baeb72SSatish Balay /*@
1668dc4c0fb0SBarry Smith    SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
16699b94acceSBarry Smith 
1670d083f849SBarry Smith    Collective
1671c7afd0dbSLois Curfman McInnes 
1672f6dfbefdSBarry Smith    Input Parameter:
1673906ed7ccSBarry Smith .  comm - MPI communicator
16749b94acceSBarry Smith 
16759b94acceSBarry Smith    Output Parameter:
1676*20f4b53cSBarry Smith .  outsnes - the new `SNES` context
16779b94acceSBarry Smith 
1678c7afd0dbSLois Curfman McInnes    Options Database Keys:
1679dc4c0fb0SBarry Smith +   -snes_mf - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1680dc4c0fb0SBarry Smith .   -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1681dc4c0fb0SBarry Smith                as set by `SNESSetJacobian()`
1682dc4c0fb0SBarry Smith .   -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1683c7afd0dbSLois Curfman McInnes -   -snes_fd - Uses (slow!) finite differences to compute Jacobian
1684c1f60f51SBarry Smith 
168536851e7fSLois Curfman McInnes    Level: beginner
168636851e7fSLois Curfman McInnes 
168795452b02SPatrick Sanan    Developer Notes:
1688f6dfbefdSBarry Smith    `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1689efd4aadfSBarry Smith    unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1690f6dfbefdSBarry Smith    particular method does use `KSP` and regulates if the information about the `KSP` is printed
1691f6dfbefdSBarry Smith    in `SNESView()`.
1692efd4aadfSBarry Smith 
1693f6dfbefdSBarry Smith    `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1694f6dfbefdSBarry Smith    by help messages about meaningless `SNES` options.
1695f6dfbefdSBarry Smith 
1696dc4c0fb0SBarry Smith    `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1697efd4aadfSBarry Smith 
1698dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
16999b94acceSBarry Smith @*/
1700d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1701d71ae5a4SJacob Faibussowitsch {
17029b94acceSBarry Smith   SNES       snes;
1703fa9f3622SBarry Smith   SNESKSPEW *kctx;
170437fcc0dbSBarry Smith 
17053a40ed3dSBarry Smith   PetscFunctionBegin;
1706ed1caa07SMatthew Knepley   PetscValidPointer(outsnes, 2);
17070298fd71SBarry Smith   *outsnes = NULL;
17089566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17098ba1e511SMatthew Knepley 
17109566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17117adad957SLisandro Dalcin 
17128d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
17132c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
171488976e71SPeter Brune   snes->tolerancesset  = PETSC_FALSE;
17159b94acceSBarry Smith   snes->max_its        = 50;
17169750a799SBarry Smith   snes->max_funcs      = 10000;
17179b94acceSBarry Smith   snes->norm           = 0.0;
1718c1e67a49SFande Kong   snes->xnorm          = 0.0;
1719c1e67a49SFande Kong   snes->ynorm          = 0.0;
1720365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
17216c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
17223a2046daSBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
17233a2046daSBarry Smith   snes->rtol = 1.e-5;
17243a2046daSBarry Smith #else
1725b4874afaSBarry Smith   snes->rtol = 1.e-8;
17263a2046daSBarry Smith #endif
1727b4874afaSBarry Smith   snes->ttol = 0.0;
17283a2046daSBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
17293a2046daSBarry Smith   snes->abstol = 1.e-25;
17303a2046daSBarry Smith #else
173170441072SBarry Smith   snes->abstol = 1.e-50;
17323a2046daSBarry Smith #endif
17337cd0ae37SLisandro Dalcin #if defined(PETSC_USE_REAL_SINGLE)
17347cd0ae37SLisandro Dalcin   snes->stol = 1.e-5;
17357cd0ae37SLisandro Dalcin #else
1736c60f73f4SPeter Brune   snes->stol = 1.e-8;
17377cd0ae37SLisandro Dalcin #endif
17383a2046daSBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
17393a2046daSBarry Smith   snes->deltatol = 1.e-6;
17403a2046daSBarry Smith #else
17414b27c08aSLois Curfman McInnes   snes->deltatol = 1.e-12;
17423a2046daSBarry Smith #endif
1743e37c518bSBarry Smith   snes->divtol               = 1.e4;
1744e37c518bSBarry Smith   snes->rnorm0               = 0;
17459b94acceSBarry Smith   snes->nfuncs               = 0;
174650ffb88aSMatthew Knepley   snes->numFailures          = 0;
174750ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17487a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1749e35cf81dSBarry Smith   snes->lagjacobian          = 1;
175037ec4e1aSPeter Brune   snes->jac_iter             = 0;
175137ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1752a8054027SBarry Smith   snes->lagpreconditioner    = 1;
175337ec4e1aSPeter Brune   snes->pre_iter             = 0;
175437ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1755639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1756c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17579e5d0892SLisandro Dalcin   snes->data                 = NULL;
17584dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1759186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17606f24a144SLois Curfman McInnes   snes->nwork                = 0;
17619e5d0892SLisandro Dalcin   snes->work                 = NULL;
176258c9b817SLisandro Dalcin   snes->nvwork               = 0;
17639e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1764758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1765758f92a0SBarry Smith   snes->conv_hist_max        = 0;
17660298fd71SBarry Smith   snes->conv_hist            = NULL;
17670298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1768758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1769971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1770e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1771184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1772efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1773b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1774c40d0f55SPeter Brune 
1775d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1776d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1777d8f46077SPeter Brune   snes->mf_version  = 1;
1778d8f46077SPeter Brune 
17793d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
17803d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
17813d4c4710SBarry Smith 
1782349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
178376bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1784349187a7SBarry Smith 
17854fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
17864fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
17874fc747eaSLawrence Mitchell 
17889b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
17894dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1790f5af7f23SKarl Rupp 
17919b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
17929b94acceSBarry Smith   kctx->version     = 2;
17930f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
17949b94acceSBarry Smith                              this was too large for some test cases */
179575567043SBarry Smith   kctx->rtol_last   = 0.0;
17960f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
17979b94acceSBarry Smith   kctx->gamma       = 1.0;
17980f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
179971f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
18000f0abf79SStefano Zampini   kctx->threshold   = 0.1;
180175567043SBarry Smith   kctx->lresid_last = 0.0;
180275567043SBarry Smith   kctx->norm_last   = 0.0;
18039b94acceSBarry Smith 
18040f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
18050f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
18060f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
18070f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
18080f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
18090f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
18100f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
18110f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
18120f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
18130f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
18140f0abf79SStefano Zampini 
18159b94acceSBarry Smith   *outsnes = snes;
18163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18179b94acceSBarry Smith }
18189b94acceSBarry Smith 
181988f0584fSBarry Smith /*MC
1820f6dfbefdSBarry Smith     SNESFunction - Functional form used to convey the nonlinear function to `SNES` in `SNESSetFunction()`
182188f0584fSBarry Smith 
182288f0584fSBarry Smith      Synopsis:
1823411c0326SBarry Smith      #include "petscsnes.h"
1824411c0326SBarry Smith      PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
182588f0584fSBarry Smith 
1826c3339decSBarry Smith      Collective
18271843f636SBarry Smith 
182888f0584fSBarry Smith      Input Parameters:
1829f6dfbefdSBarry Smith +     snes - the `SNES` context
183088f0584fSBarry Smith .     x    - state at which to evaluate residual
1831f6dfbefdSBarry Smith -     ctx     - optional user-defined function context, passed in with `SNESSetFunction()`
183288f0584fSBarry Smith 
183388f0584fSBarry Smith      Output Parameter:
183488f0584fSBarry Smith .     f  - vector to put residual (function value)
183588f0584fSBarry Smith 
1836878cb397SSatish Balay    Level: intermediate
1837878cb397SSatish Balay 
1838dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetFunction()`, `SNESGetFunction()`
183988f0584fSBarry Smith M*/
184088f0584fSBarry Smith 
18419b94acceSBarry Smith /*@C
18429b94acceSBarry Smith    SNESSetFunction - Sets the function evaluation routine and function
1843f6dfbefdSBarry Smith    vector for use by the `SNES` routines in solving systems of nonlinear
18449b94acceSBarry Smith    equations.
18459b94acceSBarry Smith 
1846c3339decSBarry Smith    Logically Collective
1847fee21e36SBarry Smith 
1848c7afd0dbSLois Curfman McInnes    Input Parameters:
1849f6dfbefdSBarry Smith +  snes - the `SNES` context
1850dc4c0fb0SBarry Smith .  r - vector to store function values, may be `NULL`
1851*20f4b53cSBarry Smith .  f - function evaluation routine;  for calling sequence see `SNESFunction`
1852c7afd0dbSLois Curfman McInnes -  ctx - [optional] user-defined context for private data for the
1853dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
18549b94acceSBarry Smith 
185536851e7fSLois Curfman McInnes    Level: beginner
185636851e7fSLois Curfman McInnes 
1857dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunction`
18589b94acceSBarry Smith @*/
1859d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunction(SNES snes, Vec r, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
1860d71ae5a4SJacob Faibussowitsch {
18616cab3a1bSJed Brown   DM dm;
18626cab3a1bSJed Brown 
18633a40ed3dSBarry Smith   PetscFunctionBegin;
18640700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1865d2a683ecSLisandro Dalcin   if (r) {
1866d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1867d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18689566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18699566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
187085385478SLisandro Dalcin     snes->vec_func = r;
1871d2a683ecSLisandro Dalcin   }
18729566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18739566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
187448a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18769b94acceSBarry Smith }
18779b94acceSBarry Smith 
1878e4ed7901SPeter Brune /*@C
1879e4ed7901SPeter Brune    SNESSetInitialFunction - Sets the function vector to be used as the
1880f6dfbefdSBarry Smith    initial function value at the initialization of the method.  In some
1881e4ed7901SPeter Brune    instances, the user has precomputed the function before calling
1882f6dfbefdSBarry Smith    `SNESSolve()`.  This function allows one to avoid a redundant call
1883f6dfbefdSBarry Smith    to `SNESComputeFunction()` in that case.
1884e4ed7901SPeter Brune 
1885c3339decSBarry Smith    Logically Collective
1886e4ed7901SPeter Brune 
1887e4ed7901SPeter Brune    Input Parameters:
1888f6dfbefdSBarry Smith +  snes - the `SNES` context
1889e4ed7901SPeter Brune -  f - vector to store function value
1890e4ed7901SPeter Brune 
1891dc4c0fb0SBarry Smith    Level: developer
1892dc4c0fb0SBarry Smith 
1893e4ed7901SPeter Brune    Notes:
1894e4ed7901SPeter Brune    This should not be modified during the solution procedure.
1895e4ed7901SPeter Brune 
1896f6dfbefdSBarry Smith    This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1897e4ed7901SPeter Brune 
1898dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1899e4ed7901SPeter Brune @*/
1900d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1901d71ae5a4SJacob Faibussowitsch {
1902e4ed7901SPeter Brune   Vec vec_func;
1903e4ed7901SPeter Brune 
1904e4ed7901SPeter Brune   PetscFunctionBegin;
1905e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1906e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1907e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1908efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1909902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19103ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1911902f982fSPeter Brune   }
19129566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19139566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1914f5af7f23SKarl Rupp 
1915217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1917e4ed7901SPeter Brune }
1918e4ed7901SPeter Brune 
1919534ebe21SPeter Brune /*@
1920f6dfbefdSBarry Smith    SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1921f6dfbefdSBarry Smith    of the `SNES` method, when norms are computed in the solving process
1922534ebe21SPeter Brune 
1923c3339decSBarry Smith    Logically Collective
1924534ebe21SPeter Brune 
1925534ebe21SPeter Brune    Input Parameters:
1926f6dfbefdSBarry Smith +  snes - the `SNES` context
1927365a6726SPeter Brune -  normschedule - the frequency of norm computation
1928534ebe21SPeter Brune 
1929517f1916SMatthew G. Knepley    Options Database Key:
193067b8a455SSatish Balay .  -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1931517f1916SMatthew G. Knepley 
1932dc4c0fb0SBarry Smith    Level: advanced
1933dc4c0fb0SBarry Smith 
1934534ebe21SPeter Brune    Notes:
1935f6dfbefdSBarry Smith    Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1936534ebe21SPeter Brune    of the nonlinear function and the taking of its norm at every iteration to
1937534ebe21SPeter Brune    even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1938f6dfbefdSBarry Smith    `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1939534ebe21SPeter Brune    may either be monitored for convergence or not.  As these are often used as nonlinear
1940534ebe21SPeter Brune    preconditioners, monitoring the norm of their error is not a useful enterprise within
1941534ebe21SPeter Brune    their solution.
1942534ebe21SPeter Brune 
1943dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1944534ebe21SPeter Brune @*/
1945d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1946d71ae5a4SJacob Faibussowitsch {
1947534ebe21SPeter Brune   PetscFunctionBegin;
1948534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1949365a6726SPeter Brune   snes->normschedule = normschedule;
19503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1951534ebe21SPeter Brune }
1952534ebe21SPeter Brune 
1953534ebe21SPeter Brune /*@
1954f6dfbefdSBarry Smith    SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1955f6dfbefdSBarry Smith    of the `SNES` method.
1956534ebe21SPeter Brune 
1957c3339decSBarry Smith    Logically Collective
1958534ebe21SPeter Brune 
1959534ebe21SPeter Brune    Input Parameters:
1960f6dfbefdSBarry Smith +  snes - the `SNES` context
1961365a6726SPeter Brune -  normschedule - the type of the norm used
1962534ebe21SPeter Brune 
1963534ebe21SPeter Brune    Level: advanced
1964534ebe21SPeter Brune 
1965dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1966534ebe21SPeter Brune @*/
1967d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1968d71ae5a4SJacob Faibussowitsch {
1969534ebe21SPeter Brune   PetscFunctionBegin;
1970534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1971365a6726SPeter Brune   *normschedule = snes->normschedule;
19723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1973534ebe21SPeter Brune }
1974534ebe21SPeter Brune 
1975c5ce4427SMatthew G. Knepley /*@
1976c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1977c5ce4427SMatthew G. Knepley 
1978c3339decSBarry Smith   Logically Collective
1979c5ce4427SMatthew G. Knepley 
1980c5ce4427SMatthew G. Knepley   Input Parameters:
1981f6dfbefdSBarry Smith +  snes - the `SNES` context
1982f6dfbefdSBarry Smith -  norm - the value of the norm
1983c5ce4427SMatthew G. Knepley 
1984c5ce4427SMatthew G. Knepley   Level: developer
1985c5ce4427SMatthew G. Knepley 
1986dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1987c5ce4427SMatthew G. Knepley @*/
1988d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1989d71ae5a4SJacob Faibussowitsch {
1990c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1991c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1992c5ce4427SMatthew G. Knepley   snes->norm = norm;
19933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1994c5ce4427SMatthew G. Knepley }
1995c5ce4427SMatthew G. Knepley 
1996c5ce4427SMatthew G. Knepley /*@
1997c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
1998c5ce4427SMatthew G. Knepley 
1999c5ce4427SMatthew G. Knepley   Not Collective
2000c5ce4427SMatthew G. Knepley 
2001c5ce4427SMatthew G. Knepley   Input Parameter:
2002f6dfbefdSBarry Smith . snes - the `SNES` context
2003c5ce4427SMatthew G. Knepley 
2004c5ce4427SMatthew G. Knepley   Output Parameter:
2005c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2006c5ce4427SMatthew G. Knepley 
2007c5ce4427SMatthew G. Knepley   Level: developer
2008c5ce4427SMatthew G. Knepley 
2009dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2010c5ce4427SMatthew G. Knepley @*/
2011d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2012d71ae5a4SJacob Faibussowitsch {
2013c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2014c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2015dadcf809SJacob Faibussowitsch   PetscValidRealPointer(norm, 2);
2016c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2018c5ce4427SMatthew G. Knepley }
2019c5ce4427SMatthew G. Knepley 
2020c1e67a49SFande Kong /*@
2021f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2022c1e67a49SFande Kong 
2023c1e67a49SFande Kong   Not Collective
2024c1e67a49SFande Kong 
2025c1e67a49SFande Kong   Input Parameter:
2026f6dfbefdSBarry Smith . snes - the `SNES` context
2027c1e67a49SFande Kong 
2028c1e67a49SFande Kong   Output Parameter:
2029c1e67a49SFande Kong . ynorm - the last computed update norm
2030c1e67a49SFande Kong 
2031c1e67a49SFande Kong   Level: developer
2032c1e67a49SFande Kong 
2033f6dfbefdSBarry Smith   Note:
2034f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2035f6dfbefdSBarry Smith 
2036dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2037c1e67a49SFande Kong @*/
2038d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2039d71ae5a4SJacob Faibussowitsch {
2040c1e67a49SFande Kong   PetscFunctionBegin;
2041c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2042dadcf809SJacob Faibussowitsch   PetscValidRealPointer(ynorm, 2);
2043c1e67a49SFande Kong   *ynorm = snes->ynorm;
20443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2045c1e67a49SFande Kong }
2046c1e67a49SFande Kong 
2047c1e67a49SFande Kong /*@
20484591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2049c1e67a49SFande Kong 
2050c1e67a49SFande Kong   Not Collective
2051c1e67a49SFande Kong 
2052c1e67a49SFande Kong   Input Parameter:
2053f6dfbefdSBarry Smith . snes - the `SNES` context
2054c1e67a49SFande Kong 
2055c1e67a49SFande Kong   Output Parameter:
2056c1e67a49SFande Kong . xnorm - the last computed solution norm
2057c1e67a49SFande Kong 
2058c1e67a49SFande Kong   Level: developer
2059c1e67a49SFande Kong 
2060dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2061c1e67a49SFande Kong @*/
2062d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2063d71ae5a4SJacob Faibussowitsch {
2064c1e67a49SFande Kong   PetscFunctionBegin;
2065c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2066dadcf809SJacob Faibussowitsch   PetscValidRealPointer(xnorm, 2);
2067c1e67a49SFande Kong   *xnorm = snes->xnorm;
20683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2069c1e67a49SFande Kong }
2070c1e67a49SFande Kong 
207147073ea2SPeter Brune /*@C
2072f6dfbefdSBarry Smith    SNESSetFunctionType - Sets the `SNESFunctionType`
2073f6dfbefdSBarry Smith    of the `SNES` method.
207447073ea2SPeter Brune 
2075c3339decSBarry Smith    Logically Collective
207647073ea2SPeter Brune 
207747073ea2SPeter Brune    Input Parameters:
2078f6dfbefdSBarry Smith +  snes - the `SNES` context
2079f6dfbefdSBarry Smith -  type - the function type
208047073ea2SPeter Brune 
208147073ea2SPeter Brune    Level: developer
208247073ea2SPeter Brune 
2083f6dfbefdSBarry Smith    Notes:
2084f6dfbefdSBarry Smith    Possible values of the function type
2085f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType`
2086f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2087f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()`
2088f6dfbefdSBarry Smith 
2089f6dfbefdSBarry Smith    Different `SNESType`s use this value in different ways
2090f6dfbefdSBarry Smith 
2091dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
209247073ea2SPeter Brune @*/
2093d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2094d71ae5a4SJacob Faibussowitsch {
209547073ea2SPeter Brune   PetscFunctionBegin;
209647073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
209747073ea2SPeter Brune   snes->functype = type;
20983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209947073ea2SPeter Brune }
210047073ea2SPeter Brune 
210147073ea2SPeter Brune /*@C
2102f6dfbefdSBarry Smith    SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
210347073ea2SPeter Brune    of the SNES method.
210447073ea2SPeter Brune 
2105c3339decSBarry Smith    Logically Collective
210647073ea2SPeter Brune 
210747073ea2SPeter Brune    Input Parameters:
2108f6dfbefdSBarry Smith +  snes - the `SNES` context
2109f6dfbefdSBarry Smith -  type - the type of the function evaluation, see `SNESSetFunctionType()`
211047073ea2SPeter Brune 
211147073ea2SPeter Brune    Level: advanced
211247073ea2SPeter Brune 
2113dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
211447073ea2SPeter Brune @*/
2115d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2116d71ae5a4SJacob Faibussowitsch {
211747073ea2SPeter Brune   PetscFunctionBegin;
211847073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
211947073ea2SPeter Brune   *type = snes->functype;
21203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2121534ebe21SPeter Brune }
2122534ebe21SPeter Brune 
2123bf388a1fSBarry Smith /*MC
2124f6dfbefdSBarry Smith     SNESNGSFunction - function used to apply a Gauss-Seidel sweep on the nonlinear function
2125bf388a1fSBarry Smith 
2126bf388a1fSBarry Smith      Synopsis:
2127aaa7dc30SBarry Smith      #include <petscsnes.h>
2128be95d8f1SBarry Smith $    SNESNGSFunction(SNES snes,Vec x,Vec b,void *ctx);
2129bf388a1fSBarry Smith 
2130c3339decSBarry Smith      Collective
21311843f636SBarry Smith 
21321843f636SBarry Smith      Input Parameters:
2133bf388a1fSBarry Smith +  X   - solution vector
2134bf388a1fSBarry Smith .  B   - RHS vector
2135bf388a1fSBarry Smith -  ctx - optional user-defined Gauss-Seidel context
2136bf388a1fSBarry Smith 
21371843f636SBarry Smith      Output Parameter:
21381843f636SBarry Smith .  X   - solution vector
21391843f636SBarry Smith 
2140878cb397SSatish Balay    Level: intermediate
2141878cb397SSatish Balay 
2142dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESNGS`, `SNESSetNGS()`, `SNESGetNGS()`
2143bf388a1fSBarry Smith M*/
2144bf388a1fSBarry Smith 
2145c79ef259SPeter Brune /*@C
2146be95d8f1SBarry Smith    SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2147c79ef259SPeter Brune    use with composed nonlinear solvers.
2148c79ef259SPeter Brune 
2149c79ef259SPeter Brune    Input Parameters:
2150dc4c0fb0SBarry Smith +  snes   - the `SNES` context
2151f6dfbefdSBarry Smith .  f - function evaluation routine to apply Gauss-Seidel see `SNESNGSFunction`
2152c79ef259SPeter Brune -  ctx    - [optional] user-defined context for private data for the
2153dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2154c79ef259SPeter Brune 
2155*20f4b53cSBarry Smith    Calling sequence of `f`:
2156*20f4b53cSBarry Smith $  PetscErrorCode f(SNES snes, Vec X, Vec B, void *ctx)
2157f6dfbefdSBarry Smith +  snes - the `SNES` context
2158f6dfbefdSBarry Smith .  X - the current solution
2159dc4c0fb0SBarry Smith .  B - the right hand side vector (which may be `NULL`)
2160f6dfbefdSBarry Smith -  ctx - a user provided context
2161f6dfbefdSBarry Smith 
2162dc4c0fb0SBarry Smith    Level: intermediate
2163dc4c0fb0SBarry Smith 
2164f6dfbefdSBarry Smith    Note:
2165f6dfbefdSBarry Smith    The `SNESNGS` routines are used by the composed nonlinear solver to generate
2166f6dfbefdSBarry Smith     a problem appropriate update to the solution, particularly `SNESFAS`.
2167c79ef259SPeter Brune 
2168dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetNGS()`, `SNESNGSFunction`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`
2169c79ef259SPeter Brune @*/
2170d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNGS(SNES snes, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
2171d71ae5a4SJacob Faibussowitsch {
21726cab3a1bSJed Brown   DM dm;
21736cab3a1bSJed Brown 
2174646217ecSPeter Brune   PetscFunctionBegin;
21756cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21769566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21779566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2179646217ecSPeter Brune }
2180646217ecSPeter Brune 
2181bbc1464cSBarry Smith /*
2182bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2183bbc1464cSBarry Smith    changed during the KSPSolve()
2184bbc1464cSBarry Smith */
2185d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2186d71ae5a4SJacob Faibussowitsch {
2187bbc1464cSBarry Smith   DM     dm;
2188bbc1464cSBarry Smith   DMSNES sdm;
2189bbc1464cSBarry Smith 
2190bbc1464cSBarry Smith   PetscFunctionBegin;
21919566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21929566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2193bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2194bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2195792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21969566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21970df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2198ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2199792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22009566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2201bbc1464cSBarry Smith   } else {
2202792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22039566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2204bbc1464cSBarry Smith   }
22053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2206bbc1464cSBarry Smith }
2207bbc1464cSBarry Smith 
2208d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2209d71ae5a4SJacob Faibussowitsch {
2210e03ab78fSPeter Brune   DM     dm;
2211942e3340SBarry Smith   DMSNES sdm;
22126cab3a1bSJed Brown 
22138b0a5094SBarry Smith   PetscFunctionBegin;
22149566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22159566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22168b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2217bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2218792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22199566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2220792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22219566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2222bbc1464cSBarry Smith   } else {
2223792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22249566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2225bbc1464cSBarry Smith   }
22263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22278b0a5094SBarry Smith }
22288b0a5094SBarry Smith 
2229d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2230d71ae5a4SJacob Faibussowitsch {
22318b0a5094SBarry Smith   PetscFunctionBegin;
2232e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2233bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22349566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22359566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22378b0a5094SBarry Smith }
22388b0a5094SBarry Smith 
22398b0a5094SBarry Smith /*@C
2240f6dfbefdSBarry Smith    SNESSetPicard - Use `SNES` to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization)
22418b0a5094SBarry Smith 
2242c3339decSBarry Smith    Logically Collective
22438b0a5094SBarry Smith 
22448b0a5094SBarry Smith    Input Parameters:
2245f6dfbefdSBarry Smith +  snes - the `SNES` context
2246dc4c0fb0SBarry Smith .  r - vector to store function values, may be `NULL`
2247dc4c0fb0SBarry Smith .  bp - function evaluation routine, may be `NULL`
22486b7fb656SBarry Smith .  Amat - matrix with which A(x) x - bp(x) - b is to be computed
2249dc4c0fb0SBarry Smith .  Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
2250*20f4b53cSBarry Smith .  J  - function to compute matrix values, for the calling sequence see `SNESJacobianFunction()`
2251dc4c0fb0SBarry Smith -  ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2252dc4c0fb0SBarry Smith 
2253dc4c0fb0SBarry Smith    Level: intermediate
22548b0a5094SBarry Smith 
22558b0a5094SBarry Smith    Notes:
22566b7fb656SBarry Smith     It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2257f450aa47SBarry 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.
2258f450aa47SBarry Smith 
2259f6dfbefdSBarry Smith     One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22608b0a5094SBarry Smith 
2261dc4c0fb0SBarry 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}.
2262dc4c0fb0SBarry Smith      When an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration.
22638b0a5094SBarry Smith 
2264dc4c0fb0SBarry Smith      Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22658b0a5094SBarry Smith 
22660d04baf8SBarry Smith    We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22676b7fb656SBarry Smith    the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b
22688b0a5094SBarry Smith 
22698b0a5094SBarry 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
22708b0a5094SBarry 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
22718b0a5094SBarry Smith    different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
22728b0a5094SBarry Smith 
2273dc4c0fb0SBarry 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
2274f6dfbefdSBarry Smith     A(x^{n}) is used to build the preconditioner
22756b7fb656SBarry Smith 
2276dc4c0fb0SBarry 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.
22776b7fb656SBarry Smith 
2278dc4c0fb0SBarry 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
22796b7fb656SBarry 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
2280f6dfbefdSBarry 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`.
22816b7fb656SBarry Smith    See the commment in src/snes/tutorials/ex15.c.
2282bbc1464cSBarry Smith 
2283dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, `SNESJacobianFunction`
22848b0a5094SBarry Smith @*/
2285d71ae5a4SJacob 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)
2286d71ae5a4SJacob Faibussowitsch {
2287e03ab78fSPeter Brune   DM dm;
2288e03ab78fSPeter Brune 
22898b0a5094SBarry Smith   PetscFunctionBegin;
22908b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22919566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22929566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22939566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22949566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22959566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22978b0a5094SBarry Smith }
22988b0a5094SBarry Smith 
22997971a8bfSPeter Brune /*@C
23007971a8bfSPeter Brune    SNESGetPicard - Returns the context for the Picard iteration
23017971a8bfSPeter Brune 
2302f6dfbefdSBarry Smith    Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23037971a8bfSPeter Brune 
23047971a8bfSPeter Brune    Input Parameter:
2305f6dfbefdSBarry Smith .  snes - the `SNES` context
23067971a8bfSPeter Brune 
2307d8d19677SJose E. Roman    Output Parameters:
2308dc4c0fb0SBarry Smith +  r - the function (or `NULL`)
2309*20f4b53cSBarry Smith .  f - the function (or `NULL`);  for calling sequence see `SNESFunction`
2310dc4c0fb0SBarry Smith .  Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2311dc4c0fb0SBarry Smith .  Pmat  - the matrix from which the preconditioner will be constructed (or `NULL`)
2312*20f4b53cSBarry Smith .  J - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFunction`
2313dc4c0fb0SBarry Smith -  ctx - the function context (or `NULL`)
23147971a8bfSPeter Brune 
23157971a8bfSPeter Brune    Level: advanced
23167971a8bfSPeter Brune 
2317dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunction`, `SNESJacobianFunction`
23187971a8bfSPeter Brune @*/
2319d71ae5a4SJacob 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)
2320d71ae5a4SJacob Faibussowitsch {
23217971a8bfSPeter Brune   DM dm;
23227971a8bfSPeter Brune 
23237971a8bfSPeter Brune   PetscFunctionBegin;
23247971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23259566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23269566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23279566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23289566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23307971a8bfSPeter Brune }
23317971a8bfSPeter Brune 
2332d25893d9SBarry Smith /*@C
2333dc4c0fb0SBarry Smith    SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2334d25893d9SBarry Smith 
2335c3339decSBarry Smith    Logically Collective
2336d25893d9SBarry Smith 
2337d25893d9SBarry Smith    Input Parameters:
2338f6dfbefdSBarry Smith +  snes - the `SNES` context
2339d25893d9SBarry Smith .  func - function evaluation routine
2340d25893d9SBarry Smith -  ctx - [optional] user-defined context for private data for the
2341dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2342d25893d9SBarry Smith 
2343*20f4b53cSBarry Smith    Calling sequence of `func`:
2344*20f4b53cSBarry Smith $    PetscErrorCode func(SNES snes, Vec x, void *ctx);
2345*20f4b53cSBarry Smith +  snes - the `SNES` solver
2346*20f4b53cSBarry Smith .  x - vector to put initial guess
2347d25893d9SBarry Smith -  ctx - optional user-defined function context
2348d25893d9SBarry Smith 
2349d25893d9SBarry Smith    Level: intermediate
2350d25893d9SBarry Smith 
2351dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`
2352d25893d9SBarry Smith @*/
2353d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeInitialGuess(SNES snes, PetscErrorCode (*func)(SNES, Vec, void *), void *ctx)
2354d71ae5a4SJacob Faibussowitsch {
2355d25893d9SBarry Smith   PetscFunctionBegin;
2356d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2357d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2358d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2360d25893d9SBarry Smith }
2361d25893d9SBarry Smith 
23621096aae1SMatthew Knepley /*@C
2363dc4c0fb0SBarry Smith    SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
23641096aae1SMatthew Knepley    it assumes a zero right hand side.
23651096aae1SMatthew Knepley 
2366c3339decSBarry Smith    Logically Collective
23671096aae1SMatthew Knepley 
23681096aae1SMatthew Knepley    Input Parameter:
2369f6dfbefdSBarry Smith .  snes - the `SNES` context
23701096aae1SMatthew Knepley 
23711096aae1SMatthew Knepley    Output Parameter:
2372dc4c0fb0SBarry Smith .  rhs - the right hand side vector or `NULL` if the right hand side vector is null
23731096aae1SMatthew Knepley 
23741096aae1SMatthew Knepley    Level: intermediate
23751096aae1SMatthew Knepley 
2376dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23771096aae1SMatthew Knepley @*/
2378d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2379d71ae5a4SJacob Faibussowitsch {
23801096aae1SMatthew Knepley   PetscFunctionBegin;
23810700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23821096aae1SMatthew Knepley   PetscValidPointer(rhs, 2);
238385385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23851096aae1SMatthew Knepley }
23861096aae1SMatthew Knepley 
23879b94acceSBarry Smith /*@
2388f6dfbefdSBarry Smith    SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23899b94acceSBarry Smith 
2390c3339decSBarry Smith    Collective
2391c7afd0dbSLois Curfman McInnes 
23929b94acceSBarry Smith    Input Parameters:
2393f6dfbefdSBarry Smith +  snes - the `SNES` context
2394c7afd0dbSLois Curfman McInnes -  x - input vector
23959b94acceSBarry Smith 
23969b94acceSBarry Smith    Output Parameter:
2397f6dfbefdSBarry Smith .  y - function vector, as set by `SNESSetFunction()`
23989b94acceSBarry Smith 
2399dc4c0fb0SBarry Smith    Level: developer
2400dc4c0fb0SBarry Smith 
2401f6dfbefdSBarry Smith    Note:
2402f6dfbefdSBarry Smith    `SNESComputeFunction()` is typically used within nonlinear solvers
2403bbc1464cSBarry Smith    implementations, so users would not generally call this routine themselves.
240436851e7fSLois Curfman McInnes 
2405dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24069b94acceSBarry Smith @*/
2407d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2408d71ae5a4SJacob Faibussowitsch {
24096cab3a1bSJed Brown   DM     dm;
2410942e3340SBarry Smith   DMSNES sdm;
24119b94acceSBarry Smith 
24123a40ed3dSBarry Smith   PetscFunctionBegin;
24130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24140700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24150700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2416c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2417c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2418e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2419184914b5SBarry Smith 
24209566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24219566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24220fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computefunction || snes->vec_rhs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve().");
242332f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
242448a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24259566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24268ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24278ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2428800f99ffSJeremy L Thompson     {
2429800f99ffSJeremy L Thompson       void *ctx;
2430800f99ffSJeremy L Thompson       PetscErrorCode (*computefunction)(SNES, Vec, Vec, void *);
2431800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2432800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2433800f99ffSJeremy L Thompson     }
24349566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
243548a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24360fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24379566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24380fdf79fbSJacob Faibussowitsch   }
24391baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2440ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2441422a814eSBarry Smith   /*
2442422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2443422a814eSBarry Smith      propagate the value to all processes
2444422a814eSBarry Smith   */
24451baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24479b94acceSBarry Smith }
24489b94acceSBarry Smith 
2449c79ef259SPeter Brune /*@
2450f6dfbefdSBarry Smith    SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2451bbc1464cSBarry Smith 
2452c3339decSBarry Smith    Collective
2453bbc1464cSBarry Smith 
2454bbc1464cSBarry Smith    Input Parameters:
2455f6dfbefdSBarry Smith +  snes - the `SNES` context
2456bbc1464cSBarry Smith -  x - input vector
2457bbc1464cSBarry Smith 
2458bbc1464cSBarry Smith    Output Parameter:
2459f6dfbefdSBarry Smith .  y - function vector, as set by `SNESSetMFFunction()`
2460bbc1464cSBarry Smith 
2461dc4c0fb0SBarry Smith    Level: developer
2462dc4c0fb0SBarry 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 
2471dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2472bbc1464cSBarry Smith @*/
2473d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2474d71ae5a4SJacob Faibussowitsch {
2475bbc1464cSBarry Smith   DM     dm;
2476bbc1464cSBarry Smith   DMSNES sdm;
2477bbc1464cSBarry Smith 
2478bbc1464cSBarry Smith   PetscFunctionBegin;
2479bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2480bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2481bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2482bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2483bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2484e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2485bbc1464cSBarry Smith 
24869566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24879566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24889566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24899566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2490bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2491bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2492792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24939566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2495bbc1464cSBarry Smith   snes->nfuncs++;
2496bbc1464cSBarry Smith   /*
2497bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2498bbc1464cSBarry Smith      propagate the value to all processes
2499bbc1464cSBarry Smith   */
25001baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
25013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2502bbc1464cSBarry Smith }
2503bbc1464cSBarry Smith 
2504bbc1464cSBarry Smith /*@
2505f6dfbefdSBarry Smith    SNESComputeNGS - Calls the Gauss-Seidel function that has been set with  `SNESSetNGS()`.
2506c79ef259SPeter Brune 
2507c3339decSBarry Smith    Collective
2508c79ef259SPeter Brune 
2509c79ef259SPeter Brune    Input Parameters:
2510f6dfbefdSBarry Smith +  snes - the `SNES` context
2511c79ef259SPeter Brune .  x - input vector
2512c79ef259SPeter Brune -  b - rhs vector
2513c79ef259SPeter Brune 
2514c79ef259SPeter Brune    Output Parameter:
2515c79ef259SPeter Brune .  x - new solution vector
2516c79ef259SPeter Brune 
2517dc4c0fb0SBarry Smith    Level: developer
2518dc4c0fb0SBarry Smith 
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 
2524dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESNGS`, `SNESSetNGS()`, `SNESComputeFunction()`
2525c79ef259SPeter Brune @*/
2526d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2527d71ae5a4SJacob Faibussowitsch {
25286cab3a1bSJed Brown   DM     dm;
2529942e3340SBarry Smith   DMSNES sdm;
2530646217ecSPeter Brune 
2531646217ecSPeter Brune   PetscFunctionBegin;
2532646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2533064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2534064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2535064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2536064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2537e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25399566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25409566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25410fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25429566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2543792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25449566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2547646217ecSPeter Brune }
2548646217ecSPeter Brune 
2549d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2550d71ae5a4SJacob Faibussowitsch {
255112837594SBarry Smith   Mat               A, B, C, D, jacobian;
2552e885f1abSBarry Smith   Vec               x = snes->vec_sol, f = snes->vec_func;
2553e885f1abSBarry Smith   PetscReal         nrm, gnorm;
255481e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
25550e276705SLisandro Dalcin   MatType           mattype;
2556e885f1abSBarry Smith   PetscInt          m, n, M, N;
2557e885f1abSBarry Smith   void             *functx;
25582cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
25593325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2560e885f1abSBarry Smith   MPI_Comm          comm;
2561e885f1abSBarry Smith   PetscInt          tabs;
256212837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
25633325ff46SBarry Smith   PetscViewerFormat format;
2564e885f1abSBarry Smith 
2565e885f1abSBarry Smith   PetscFunctionBegin;
2566d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
25679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
25689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
25699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
257018d89885SKarl Rupp   if (!complete_print) {
25719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
25729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsViewer("-snes_test_jacobian_display", "Display difference between hand-coded and finite difference Jacobians", "None", &mviewer, &format, &complete_print));
257318d89885SKarl Rupp   }
257418d89885SKarl Rupp   /* for compatibility with PETSc 3.9 and older. */
25759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
25769566063dSJacob 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));
2577d0609cedSBarry Smith   PetscOptionsEnd();
25783ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2579e885f1abSBarry Smith 
25809566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
25819566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
25829566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
25839566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
25849566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
258512837594SBarry Smith   if (!complete_print && !directionsprinted) {
25869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
25879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
258812837594SBarry Smith   }
258912837594SBarry Smith   if (!directionsprinted) {
25909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
25919566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
259212837594SBarry Smith     directionsprinted = PETSC_TRUE;
2593e885f1abSBarry Smith   }
25941baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2595e885f1abSBarry Smith 
25969566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
259712837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
259812837594SBarry Smith   else jacobian = snes->jacobian_pre;
259912837594SBarry Smith 
2600a82339d0SMatthew G. Knepley   if (!x) {
26019566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(jacobian, &x, NULL));
2602a82339d0SMatthew G. Knepley   } else {
26039566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
2604a82339d0SMatthew G. Knepley   }
2605a82339d0SMatthew G. Knepley   if (!f) {
26069566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &f));
2607a82339d0SMatthew G. Knepley   } else {
26089566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)f));
2609a82339d0SMatthew G. Knepley   }
2610a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
26119566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
26129566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
26139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
261412837594SBarry Smith   while (jacobian) {
26152cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
26162cd624f9SStefano Zampini 
26172cd624f9SStefano Zampini     if (istranspose) {
26189566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
26192cd624f9SStefano Zampini       Jsave    = jacobian;
26202cd624f9SStefano Zampini       jacobian = JT;
26212cd624f9SStefano Zampini     }
26229566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
262312837594SBarry Smith     if (flg) {
262412837594SBarry Smith       A = jacobian;
26259566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
262612837594SBarry Smith     } else {
26279566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
262812837594SBarry Smith     }
2629e885f1abSBarry Smith 
26309566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
26319566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
26329566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
26339566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
26349566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
26359566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
26369566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
26379566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
26389566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2639e885f1abSBarry Smith 
26409566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
26419566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
264212837594SBarry Smith 
26439566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
26449566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26459566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
26469566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
26479566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
264812837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
26499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
265012837594SBarry Smith 
2651e885f1abSBarry Smith     if (complete_print) {
26529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
26539566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
26549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
26559566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2656e885f1abSBarry Smith     }
2657e885f1abSBarry Smith 
2658df10fb39SFande Kong     if (threshold_print || complete_print) {
2659e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2660e885f1abSBarry Smith       PetscScalar       *cvals;
2661e885f1abSBarry Smith       const PetscInt    *bcols;
2662e885f1abSBarry Smith       const PetscScalar *bvals;
2663e885f1abSBarry Smith 
26649566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
26659566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
26669566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
26679566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
26689566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
26699566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
26700e276705SLisandro Dalcin 
26719566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26729566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2673e885f1abSBarry Smith 
2674e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
26759566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
26769566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2677e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
267823a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2679e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2680e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2681e885f1abSBarry Smith             cncols += 1;
2682e885f1abSBarry Smith           }
2683e885f1abSBarry Smith         }
268448a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
26859566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
26869566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2687e885f1abSBarry Smith       }
26889566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
26899566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
26909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
26919566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
26929566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2693e885f1abSBarry Smith     }
26949566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
26959566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
26969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
26972cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
269812837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
269912837594SBarry Smith       jacobian = snes->jacobian_pre;
27009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
27019371c9d4SSatish Balay     } else jacobian = NULL;
270212837594SBarry Smith   }
27039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
27041baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
27059566063dSJacob Faibussowitsch   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
27069566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
27073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2708e885f1abSBarry Smith }
2709e885f1abSBarry Smith 
271062fef451SLois Curfman McInnes /*@
2711f6dfbefdSBarry Smith    SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
271262fef451SLois Curfman McInnes 
2713c3339decSBarry Smith    Collective
2714c7afd0dbSLois Curfman McInnes 
271562fef451SLois Curfman McInnes    Input Parameters:
2716f6dfbefdSBarry Smith +  snes - the `SNES` context
2717c7afd0dbSLois Curfman McInnes -  x - input vector
271862fef451SLois Curfman McInnes 
271962fef451SLois Curfman McInnes    Output Parameters:
2720c7afd0dbSLois Curfman McInnes +  A - Jacobian matrix
2721f6dfbefdSBarry Smith -  B - optional matrix for building the preconditioner
2722fee21e36SBarry Smith 
2723e35cf81dSBarry Smith   Options Database Keys:
272467b8a455SSatish Balay +    -snes_lag_preconditioner <lag> - how often to rebuild preconditioner
272567b8a455SSatish Balay .    -snes_lag_jacobian <lag> - how often to rebuild Jacobian
2726455a5933SJed 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.
2727455a5933SJed 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
2728693365a8SJed Brown .    -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2729693365a8SJed Brown .    -snes_compare_explicit_draw  - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2730693365a8SJed Brown .    -snes_compare_explicit_contour  - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
27314c30e9fbSJed Brown .    -snes_compare_operator  - Make the comparison options above use the operator instead of the preconditioning matrix
273294d6a431SBarry Smith .    -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference
2733a5b23f4aSJose E. Roman .    -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences
2734c01495d3SJed Brown .    -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold
2735dc4c0fb0SBarry Smith .    -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2736dc4c0fb0SBarry Smith .    -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2737a5b23f4aSJose E. Roman .    -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences
2738a5b23f4aSJose E. Roman -    -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2739c01495d3SJed Brown 
2740dc4c0fb0SBarry Smith    Level: developer
2741dc4c0fb0SBarry Smith 
2742f6dfbefdSBarry Smith    Note:
274362fef451SLois Curfman McInnes    Most users should not need to explicitly call this routine, as it
274462fef451SLois Curfman McInnes    is used internally within the nonlinear solvers.
274562fef451SLois Curfman McInnes 
2746f6dfbefdSBarry Smith    Developer Note:
2747dc4c0fb0SBarry Smith     This has duplicative ways of checking the accuracy of the user provided Jacobian (see the options above). This is for historical reasons, the routine `SNESTestJacobian()` use to used
2748dc4c0fb0SBarry Smith       for with the `SNESType` of test that has been removed.
2749e885f1abSBarry Smith 
2750dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
275162fef451SLois Curfman McInnes @*/
2752d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2753d71ae5a4SJacob Faibussowitsch {
2754ace3abfcSBarry Smith   PetscBool flag;
27556cab3a1bSJed Brown   DM        dm;
2756942e3340SBarry Smith   DMSNES    sdm;
2757e0e3a89bSBarry Smith   KSP       ksp;
27583a40ed3dSBarry Smith 
27593a40ed3dSBarry Smith   PetscFunctionBegin;
27600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
27610700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2762c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2763e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
27649566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
27659566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
27663232da50SPeter Brune 
2767ebd3b9afSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
2768fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2769fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2770f5af7f23SKarl Rupp 
27719566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2772fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
27739566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
27749566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2775ebd3b9afSBarry Smith     if (flag) {
27769566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27779566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2778ebd3b9afSBarry Smith     }
27793ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
278037ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
278163a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
27829566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2783ebd3b9afSBarry Smith     if (flag) {
27849566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27859566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2786ebd3b9afSBarry Smith     }
27873ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2788e35cf81dSBarry Smith   }
2789efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
27909566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27919566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
27923ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2793d728fb7dSPeter Brune   }
2794e35cf81dSBarry Smith 
27959566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
27969566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2797800f99ffSJeremy L Thompson   {
2798800f99ffSJeremy L Thompson     void *ctx;
2799800f99ffSJeremy L Thompson     PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *);
2800800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2801800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2802800f99ffSJeremy L Thompson   }
28039566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
28049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
280528d58a37SPierre Jolivet 
280628d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
28079566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2808a8054027SBarry Smith 
2809e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
28109566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
28113b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
28129566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
28139566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
28143b4f5425SBarry Smith     snes->lagpreconditioner = -1;
28153b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
28169566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
28179566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
281837ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
281963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
28209566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2821d1e9a80fSBarry Smith   } else {
28229566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
28239566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2824a8054027SBarry Smith   }
2825a8054027SBarry Smith 
28269566063dSJacob Faibussowitsch   PetscCall(SNESTestJacobian(snes));
28276d84be18SBarry Smith   /* make sure user returned a correct Jacobian and preconditioner */
282894ab13aaSBarry Smith   /* PetscValidHeaderSpecific(A,MAT_CLASSID,3);
282994ab13aaSBarry Smith     PetscValidHeaderSpecific(B,MAT_CLASSID,4);   */
2830693365a8SJed Brown   {
2831693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
28329566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
28339566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
28349566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
28359566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2836693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
28370298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2838693365a8SJed Brown       PetscViewer vdraw, vstdout;
28396b3a5b13SJed Brown       PetscBool   flg;
2840693365a8SJed Brown       if (flag_operator) {
28419566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2842693365a8SJed Brown         Bexp = Bexp_mine;
2843693365a8SJed Brown       } else {
2844693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
28459566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
284694ab13aaSBarry Smith         if (flg) Bexp = B;
2847693365a8SJed Brown         else {
2848693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
28499566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2850693365a8SJed Brown           Bexp = Bexp_mine;
2851693365a8SJed Brown         }
2852693365a8SJed Brown       }
28539566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
28549566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
28559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2856693365a8SJed Brown       if (flag_draw || flag_contour) {
28579566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28589566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28590298fd71SBarry Smith       } else vdraw = NULL;
28609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
28619566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
28629566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
28639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
28649566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
28659566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
28669566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
28679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
28689566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2869693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
28709566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28719566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
28729566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2873693365a8SJed Brown       }
28749566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
28759566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
28769566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
28779566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2878693365a8SJed Brown     }
2879693365a8SJed Brown   }
28804c30e9fbSJed Brown   {
28816719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
28826719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
28839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
28849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
28859566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
28869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
28879566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
288827b0f280SBarry Smith     if (flag_threshold) {
28899566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
28909566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
289127b0f280SBarry Smith     }
28926719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
28934c30e9fbSJed Brown       Mat           Bfd;
28944c30e9fbSJed Brown       PetscViewer   vdraw, vstdout;
2895335efc43SPeter Brune       MatColoring   coloring;
28964c30e9fbSJed Brown       ISColoring    iscoloring;
28974c30e9fbSJed Brown       MatFDColoring matfdcoloring;
28984c30e9fbSJed Brown       PetscErrorCode (*func)(SNES, Vec, Vec, void *);
28994c30e9fbSJed Brown       void     *funcctx;
29006719d8e4SJed Brown       PetscReal norm1, norm2, normmax;
29014c30e9fbSJed Brown 
29029566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
29039566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
29049566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
29059566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
29069566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
29079566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
29089566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
29099566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
29109566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
29119566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
29124c30e9fbSJed Brown 
29134c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
29149566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
29159566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
29169566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
29179566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
29189566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
29199566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
29209566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
29214c30e9fbSJed Brown 
29229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
29234c30e9fbSJed Brown       if (flag_draw || flag_contour) {
29249566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
29259566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29260298fd71SBarry Smith       } else vdraw = NULL;
29279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
29289566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
29299566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
29309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
29319566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29329566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
29339566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
29349566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
29359566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
29369566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
29379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
29389566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29394c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
29409566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29419566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
29429566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
29434c30e9fbSJed Brown       }
29449566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29456719d8e4SJed Brown 
29466719d8e4SJed Brown       if (flag_threshold) {
29476719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
29489566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
29499566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
29506719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
29516719d8e4SJed Brown           const PetscScalar *ba, *ca;
29526719d8e4SJed Brown           const PetscInt    *bj, *cj;
29536719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
29546719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
29559566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
29569566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
29575f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
29586719d8e4SJed Brown           for (j = 0; j < bn; j++) {
29596719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
29606719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
29616719d8e4SJed Brown               maxentrycol = bj[j];
29626719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
29636719d8e4SJed Brown             }
29646719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
29656719d8e4SJed Brown               maxdiffcol = bj[j];
29666719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
29676719d8e4SJed Brown             }
29686719d8e4SJed Brown             if (rdiff > maxrdiff) {
29696719d8e4SJed Brown               maxrdiffcol = bj[j];
29706719d8e4SJed Brown               maxrdiff    = rdiff;
29716719d8e4SJed Brown             }
29726719d8e4SJed Brown           }
29736719d8e4SJed Brown           if (maxrdiff > 1) {
297463a3b9bcSJacob 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));
29756719d8e4SJed Brown             for (j = 0; j < bn; j++) {
29766719d8e4SJed Brown               PetscReal rdiff;
29776719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
297848a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
29796719d8e4SJed Brown             }
298063a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
29816719d8e4SJed Brown           }
29829566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
29839566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
29846719d8e4SJed Brown         }
29856719d8e4SJed Brown       }
29869566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29879566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
29884c30e9fbSJed Brown     }
29894c30e9fbSJed Brown   }
29903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29919b94acceSBarry Smith }
29929b94acceSBarry Smith 
2993bf388a1fSBarry Smith /*MC
2994f6dfbefdSBarry Smith     SNESJacobianFunction - Function used by `SNES` to compute the nonlinear Jacobian of the function to be solved by `SNES`
2995bf388a1fSBarry Smith 
2996bf388a1fSBarry Smith      Synopsis:
2997411c0326SBarry Smith      #include "petscsnes.h"
2998411c0326SBarry Smith      PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
2999bf388a1fSBarry Smith 
3000c3339decSBarry Smith      Collective
30011843f636SBarry Smith 
30021843f636SBarry Smith     Input Parameters:
30031843f636SBarry Smith +  x - input vector, the Jacobian is to be computed at this value
3004bf388a1fSBarry Smith -  ctx - [optional] user-defined Jacobian context
3005bf388a1fSBarry Smith 
30061843f636SBarry Smith     Output Parameters:
30071843f636SBarry Smith +  Amat - the matrix that defines the (approximate) Jacobian
3008dc4c0fb0SBarry Smith -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
30091843f636SBarry Smith 
3010878cb397SSatish Balay    Level: intermediate
3011878cb397SSatish Balay 
3012dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESSetJacobian()`, `SNESGetJacobian()`
3013bf388a1fSBarry Smith M*/
3014bf388a1fSBarry Smith 
30159b94acceSBarry Smith /*@C
30169b94acceSBarry Smith    SNESSetJacobian - Sets the function to compute Jacobian as well as the
3017044dda88SLois Curfman McInnes    location to store the matrix.
30189b94acceSBarry Smith 
3019c3339decSBarry Smith    Logically Collective
3020c7afd0dbSLois Curfman McInnes 
30219b94acceSBarry Smith    Input Parameters:
3022f6dfbefdSBarry Smith +  snes - the `SNES` context
3023e5d3d808SBarry Smith .  Amat - the matrix that defines the (approximate) Jacobian
3024dc4c0fb0SBarry Smith .  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
3025dc4c0fb0SBarry Smith .  J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFunction` for details
3026c7afd0dbSLois Curfman McInnes -  ctx - [optional] user-defined context for private data for the
3027dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3028dc4c0fb0SBarry Smith 
3029dc4c0fb0SBarry Smith    Level: beginner
30309b94acceSBarry Smith 
30319b94acceSBarry Smith    Notes:
3032dc4c0fb0SBarry Smith    If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
303316913363SBarry Smith    each matrix.
303416913363SBarry Smith 
3035dc4c0fb0SBarry Smith    If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3036dc4c0fb0SBarry Smith    space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3037895c21f2SBarry Smith 
3038dc4c0fb0SBarry Smith    If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3039f6dfbefdSBarry Smith    must be a `MatFDColoring`.
3040a8a26c1eSJed Brown 
3041c3cc8fd1SJed Brown    Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3042f6dfbefdSBarry Smith    example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3043c3cc8fd1SJed Brown 
3044dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
3045db781477SPatrick Sanan           `SNESSetPicard()`, `SNESJacobianFunction`
30469b94acceSBarry Smith @*/
3047d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx)
3048d71ae5a4SJacob Faibussowitsch {
30496cab3a1bSJed Brown   DM dm;
30503a7fca6bSBarry Smith 
30513a40ed3dSBarry Smith   PetscFunctionBegin;
30520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3053e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3054e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3055e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3056e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
30579566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30589566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3059e5d3d808SBarry Smith   if (Amat) {
30609566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
30619566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3062f5af7f23SKarl Rupp 
3063e5d3d808SBarry Smith     snes->jacobian = Amat;
30643a7fca6bSBarry Smith   }
3065e5d3d808SBarry Smith   if (Pmat) {
30669566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
30679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3068f5af7f23SKarl Rupp 
3069e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
30703a7fca6bSBarry Smith   }
30713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30729b94acceSBarry Smith }
307362fef451SLois Curfman McInnes 
3074c2aafc4cSSatish Balay /*@C
3075b4fd4287SBarry Smith    SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3076b4fd4287SBarry Smith    provided context for evaluating the Jacobian.
3077b4fd4287SBarry Smith 
3078f6dfbefdSBarry Smith    Not Collective, but `Mat` object will be parallel if `SNES` object is
3079c7afd0dbSLois Curfman McInnes 
3080b4fd4287SBarry Smith    Input Parameter:
3081b4fd4287SBarry Smith .  snes - the nonlinear solver context
3082b4fd4287SBarry Smith 
3083b4fd4287SBarry Smith    Output Parameters:
3084dc4c0fb0SBarry Smith +  Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3085dc4c0fb0SBarry Smith .  Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
3086*20f4b53cSBarry Smith .  J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFunction`
3087dc4c0fb0SBarry Smith -  ctx - location to stash Jacobian ctx (or `NULL`)
3088fee21e36SBarry Smith 
308936851e7fSLois Curfman McInnes    Level: advanced
309036851e7fSLois Curfman McInnes 
3091dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFunction`, `SNESGetFunction()`
3092b4fd4287SBarry Smith @*/
3093d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx)
3094d71ae5a4SJacob Faibussowitsch {
30956cab3a1bSJed Brown   DM dm;
30966cab3a1bSJed Brown 
30973a40ed3dSBarry Smith   PetscFunctionBegin;
30980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3099e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3100e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
31019566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3102800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
31033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3104b4fd4287SBarry Smith }
3105b4fd4287SBarry Smith 
3106d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3107d71ae5a4SJacob Faibussowitsch {
310858b371f3SBarry Smith   DM     dm;
310958b371f3SBarry Smith   DMSNES sdm;
311058b371f3SBarry Smith 
311158b371f3SBarry Smith   PetscFunctionBegin;
31129566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31139566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
311458b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
311558b371f3SBarry Smith     DM        dm;
311658b371f3SBarry Smith     PetscBool isdense, ismf;
311758b371f3SBarry Smith 
31189566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31199566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
31209566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
312158b371f3SBarry Smith     if (isdense) {
31229566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
312358b371f3SBarry Smith     } else if (!ismf) {
31249566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
312558b371f3SBarry Smith     }
312658b371f3SBarry Smith   }
31273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
312858b371f3SBarry Smith }
312958b371f3SBarry Smith 
31309b94acceSBarry Smith /*@
31319b94acceSBarry Smith    SNESSetUp - Sets up the internal data structures for the later use
3132272ac6f2SLois Curfman McInnes    of a nonlinear solver.
31339b94acceSBarry Smith 
3134c3339decSBarry Smith    Collective
3135fee21e36SBarry Smith 
3136c7afd0dbSLois Curfman McInnes    Input Parameters:
3137f6dfbefdSBarry Smith .  snes - the `SNES` context
3138c7afd0dbSLois Curfman McInnes 
3139dc4c0fb0SBarry Smith    Level: advanced
3140dc4c0fb0SBarry Smith 
3141f6dfbefdSBarry Smith    Note:
3142f6dfbefdSBarry Smith    For basic use of the `SNES` solvers the user need not explicitly call
3143f6dfbefdSBarry Smith    `SNESSetUp()`, since these actions will automatically occur during
3144f6dfbefdSBarry Smith    the call to `SNESSolve()`.  However, if one wishes to control this
3145f6dfbefdSBarry Smith    phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3146f6dfbefdSBarry Smith    and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3147272ac6f2SLois Curfman McInnes 
3148dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
31499b94acceSBarry Smith @*/
3150d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3151d71ae5a4SJacob Faibussowitsch {
31526cab3a1bSJed Brown   DM             dm;
3153942e3340SBarry Smith   DMSNES         sdm;
3154c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
31556e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
31569b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
31579b5c1c08SStefano Zampini   Vec            f, fpc;
31589b5c1c08SStefano Zampini   void          *funcctx;
31599b5c1c08SStefano Zampini   void          *jacctx, *appctx;
31609b5c1c08SStefano Zampini   Mat            j, jpre;
31616b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
31626b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
31636e2a1849SPeter Brune   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
3164d1e9a80fSBarry Smith   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
31653a40ed3dSBarry Smith 
31663a40ed3dSBarry Smith   PetscFunctionBegin;
31670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31683ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3169fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
31709b94acceSBarry Smith 
317148a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
317285385478SLisandro Dalcin 
31739566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
317458c9b817SLisandro Dalcin 
31759566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31769566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
31779566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
317858b371f3SBarry Smith 
317948a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3180efd51863SBarry Smith 
318148a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3182b710008aSBarry Smith 
3183d8d34be6SBarry Smith   if (snes->linesearch) {
31849566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
31859566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3186d8d34be6SBarry Smith   }
31879e764e56SPeter Brune 
31889b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3189b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3190172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3191172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3192172a4300SPeter Brune   }
3193d8f46077SPeter Brune 
3194efd4aadfSBarry Smith   if (snes->npc) {
31956e2a1849SPeter Brune     /* copy the DM over */
31969566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31979566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
31986e2a1849SPeter Brune 
31999566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
32009566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
32019566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
32029566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
32039566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
32049566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
32059566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
32069b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
32079566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
32086e2a1849SPeter Brune 
32096e2a1849SPeter Brune     /* copy the function pointers over */
32109566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
32116e2a1849SPeter Brune 
32126e2a1849SPeter Brune     /* default to 1 iteration */
32139566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3214efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
32159566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3216a9936a0cSPeter Brune     } else {
32179566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3218a9936a0cSPeter Brune     }
32199566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
32206e2a1849SPeter Brune 
32216e2a1849SPeter Brune     /* copy the line search context over */
3222d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
32239566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
32249566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
32259566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
32269566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
32279566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
32289566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
32299566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
32306e2a1849SPeter Brune     }
3231d8d34be6SBarry Smith   }
32321baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
323348a46eb9SPierre Jolivet   if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user));
32346e2a1849SPeter Brune 
323537ec4e1aSPeter Brune   snes->jac_iter = 0;
323637ec4e1aSPeter Brune   snes->pre_iter = 0;
323737ec4e1aSPeter Brune 
3238dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
323958c9b817SLisandro Dalcin 
32409566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
324158b371f3SBarry Smith 
3242b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
32436c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3244d8d34be6SBarry Smith       if (snes->linesearch) {
32459566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
32469566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
32476c67d002SPeter Brune       }
32486c67d002SPeter Brune     }
3249d8d34be6SBarry Smith   }
3250fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
32517aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
32523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32539b94acceSBarry Smith }
32549b94acceSBarry Smith 
325537596af1SLisandro Dalcin /*@
3256f6dfbefdSBarry Smith    SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
325737596af1SLisandro Dalcin 
3258c3339decSBarry Smith    Collective
325937596af1SLisandro Dalcin 
326037596af1SLisandro Dalcin    Input Parameter:
3261f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
326237596af1SLisandro Dalcin 
3263d25893d9SBarry Smith    Level: intermediate
3264d25893d9SBarry Smith 
326595452b02SPatrick Sanan    Notes:
3266f6dfbefdSBarry Smith    Call this if you wish to reuse a `SNES` but with different size vectors
326737596af1SLisandro Dalcin 
3268f6dfbefdSBarry Smith    Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3269f6dfbefdSBarry Smith 
3270dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
327137596af1SLisandro Dalcin @*/
3272d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3273d71ae5a4SJacob Faibussowitsch {
327437596af1SLisandro Dalcin   PetscFunctionBegin;
327537596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3276d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
32779566063dSJacob Faibussowitsch     PetscCall((*snes->ops->userdestroy)((void **)&snes->user));
32780298fd71SBarry Smith     snes->user = NULL;
3279d25893d9SBarry Smith   }
32801baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
32818a23116dSBarry Smith 
3282dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
32831baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
32849e764e56SPeter Brune 
32851baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
32869e764e56SPeter Brune 
32879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
32889566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
32899566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
32909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
32919566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
32929566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
32939566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
32949566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
32959566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3296f5af7f23SKarl Rupp 
329740fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
329840fdac6aSLawrence Mitchell 
329937596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
330037596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
33013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
330237596af1SLisandro Dalcin }
330337596af1SLisandro Dalcin 
330452baeb72SSatish Balay /*@
3305f6dfbefdSBarry Smith    SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object.
3306c4421ceaSFande Kong 
3307c3339decSBarry Smith    Collective
3308c4421ceaSFande Kong 
3309c4421ceaSFande Kong    Input Parameter:
3310f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
3311c4421ceaSFande Kong 
3312c4421ceaSFande Kong    Level: intermediate
3313c4421ceaSFande Kong 
3314dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`
3315c4421ceaSFande Kong @*/
3316d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3317d71ae5a4SJacob Faibussowitsch {
3318c4421ceaSFande Kong   PetscInt i;
3319c4421ceaSFande Kong 
3320c4421ceaSFande Kong   PetscFunctionBegin;
3321c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3322c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
332348a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3324c4421ceaSFande Kong   }
3325c4421ceaSFande Kong   snes->numberreasonviews = 0;
33263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3327c4421ceaSFande Kong }
3328c4421ceaSFande Kong 
33291fb7b255SJunchao Zhang /*@C
33309b94acceSBarry Smith    SNESDestroy - Destroys the nonlinear solver context that was created
3331f6dfbefdSBarry Smith    with `SNESCreate()`.
33329b94acceSBarry Smith 
3333c3339decSBarry Smith    Collective
3334c7afd0dbSLois Curfman McInnes 
33359b94acceSBarry Smith    Input Parameter:
3336f6dfbefdSBarry Smith .  snes - the `SNES` context
33379b94acceSBarry Smith 
333836851e7fSLois Curfman McInnes    Level: beginner
333936851e7fSLois Curfman McInnes 
3340dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
33419b94acceSBarry Smith @*/
3342d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3343d71ae5a4SJacob Faibussowitsch {
33443a40ed3dSBarry Smith   PetscFunctionBegin;
33453ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
33466bf464f9SBarry Smith   PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1);
33479371c9d4SSatish Balay   if (--((PetscObject)(*snes))->refct > 0) {
33489371c9d4SSatish Balay     *snes = NULL;
33493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
33509371c9d4SSatish Balay   }
3351d4bb536fSBarry Smith 
33529566063dSJacob Faibussowitsch   PetscCall(SNESReset((*snes)));
33539566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
33546b8b9a38SLisandro Dalcin 
3355e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
33569566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3357dbbe0bcdSBarry Smith   PetscTryTypeMethod((*snes), destroy);
33586d4c513bSLisandro Dalcin 
33599566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
33609566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
33619566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
33629566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
33636b8b9a38SLisandro Dalcin 
33649566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
336548a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
336648a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
33679566063dSJacob Faibussowitsch   PetscCall(SNESMonitorCancel((*snes)));
33689566063dSJacob Faibussowitsch   PetscCall(SNESConvergedReasonViewCancel((*snes)));
33699566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
33703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33719b94acceSBarry Smith }
33729b94acceSBarry Smith 
33739b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
33749b94acceSBarry Smith 
3375a8054027SBarry Smith /*@
3376a8054027SBarry Smith    SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3377a8054027SBarry Smith 
3378c3339decSBarry Smith    Logically Collective
3379a8054027SBarry Smith 
3380a8054027SBarry Smith    Input Parameters:
3381f6dfbefdSBarry Smith +  snes - the `SNES` context
3382d8e291bfSBarry Smith -  lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
33833b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3384a8054027SBarry Smith 
3385a8054027SBarry Smith    Options Database Keys:
33863d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
33873d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
33883d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
33893d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3390a8054027SBarry Smith 
3391a8054027SBarry Smith    Notes:
3392dc4c0fb0SBarry Smith    Level: intermediate
3393dc4c0fb0SBarry Smith 
3394a8054027SBarry Smith    The default is 1
3395f6dfbefdSBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3396d8e291bfSBarry Smith 
3397f6dfbefdSBarry Smith    `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3398a8054027SBarry Smith 
3399dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3400f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3401a8054027SBarry Smith @*/
3402d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3403d71ae5a4SJacob Faibussowitsch {
3404a8054027SBarry Smith   PetscFunctionBegin;
34050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34065f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
34075f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3408c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3409a8054027SBarry Smith   snes->lagpreconditioner = lag;
34103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3411a8054027SBarry Smith }
3412a8054027SBarry Smith 
3413efd51863SBarry Smith /*@
3414f6dfbefdSBarry Smith    SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3415efd51863SBarry Smith 
3416c3339decSBarry Smith    Logically Collective
3417efd51863SBarry Smith 
3418efd51863SBarry Smith    Input Parameters:
3419f6dfbefdSBarry Smith +  snes - the `SNES` context
3420efd51863SBarry Smith -  steps - the number of refinements to do, defaults to 0
3421efd51863SBarry Smith 
3422f6dfbefdSBarry Smith    Options Database Key:
342367b8a455SSatish Balay .    -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3424efd51863SBarry Smith 
3425efd51863SBarry Smith    Level: intermediate
3426efd51863SBarry Smith 
3427f6dfbefdSBarry Smith    Note:
3428f6dfbefdSBarry Smith    Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3429c0df2a02SJed Brown 
3430dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`
3431efd51863SBarry Smith @*/
3432d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3433d71ae5a4SJacob Faibussowitsch {
3434efd51863SBarry Smith   PetscFunctionBegin;
3435efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3436efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3437efd51863SBarry Smith   snes->gridsequence = steps;
34383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3439efd51863SBarry Smith }
3440efd51863SBarry Smith 
3441fa19ca70SBarry Smith /*@
3442f6dfbefdSBarry Smith    SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3443fa19ca70SBarry Smith 
3444c3339decSBarry Smith    Logically Collective
3445fa19ca70SBarry Smith 
3446fa19ca70SBarry Smith    Input Parameter:
3447f6dfbefdSBarry Smith .  snes - the `SNES` context
3448fa19ca70SBarry Smith 
3449fa19ca70SBarry Smith    Output Parameter:
3450fa19ca70SBarry Smith .  steps - the number of refinements to do, defaults to 0
3451fa19ca70SBarry Smith 
3452f6dfbefdSBarry Smith    Options Database Key:
345367b8a455SSatish Balay .    -snes_grid_sequence <steps> - set number of refinements
3454fa19ca70SBarry Smith 
3455fa19ca70SBarry Smith    Level: intermediate
3456fa19ca70SBarry Smith 
3457f6dfbefdSBarry Smith    Note:
3458f6dfbefdSBarry Smith    Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3459fa19ca70SBarry Smith 
3460dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3461fa19ca70SBarry Smith @*/
3462d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3463d71ae5a4SJacob Faibussowitsch {
3464fa19ca70SBarry Smith   PetscFunctionBegin;
3465fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3466fa19ca70SBarry Smith   *steps = snes->gridsequence;
34673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3468fa19ca70SBarry Smith }
3469fa19ca70SBarry Smith 
3470a8054027SBarry Smith /*@
3471f6dfbefdSBarry Smith    SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3472a8054027SBarry Smith 
34733f9fe445SBarry Smith    Not Collective
3474a8054027SBarry Smith 
3475a8054027SBarry Smith    Input Parameter:
3476f6dfbefdSBarry Smith .  snes - the `SNES` context
3477a8054027SBarry Smith 
3478a8054027SBarry Smith    Output Parameter:
3479a8054027SBarry 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
34803b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3481a8054027SBarry Smith 
3482a8054027SBarry Smith    Options Database Keys:
34833d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
34843d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
34853d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
34863d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3487a8054027SBarry Smith 
3488dc4c0fb0SBarry Smith    Level: intermediate
3489dc4c0fb0SBarry Smith 
3490a8054027SBarry Smith    Notes:
3491a8054027SBarry Smith    The default is 1
3492f6dfbefdSBarry Smith 
3493a8054027SBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3494a8054027SBarry Smith 
3495dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3496a8054027SBarry Smith @*/
3497d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3498d71ae5a4SJacob Faibussowitsch {
3499a8054027SBarry Smith   PetscFunctionBegin;
35000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3501a8054027SBarry Smith   *lag = snes->lagpreconditioner;
35023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3503a8054027SBarry Smith }
3504a8054027SBarry Smith 
3505e35cf81dSBarry Smith /*@
3506f6dfbefdSBarry Smith    SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3507e35cf81dSBarry Smith      often the preconditioner is rebuilt.
3508e35cf81dSBarry Smith 
3509c3339decSBarry Smith    Logically Collective
3510e35cf81dSBarry Smith 
3511e35cf81dSBarry Smith    Input Parameters:
3512f6dfbefdSBarry Smith +  snes - the `SNES` context
3513e35cf81dSBarry Smith -  lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
3514fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3515e35cf81dSBarry Smith 
3516e35cf81dSBarry Smith    Options Database Keys:
35173d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
35183d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
35193d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
35203d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag.
3521e35cf81dSBarry Smith 
3522dc4c0fb0SBarry Smith    Level: intermediate
3523dc4c0fb0SBarry Smith 
3524e35cf81dSBarry Smith    Notes:
3525e35cf81dSBarry Smith    The default is 1
3526f6dfbefdSBarry Smith 
3527e35cf81dSBarry Smith    The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3528f6dfbefdSBarry Smith 
3529fe3ffe1eSBarry 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
3530fe3ffe1eSBarry Smith    at the next Newton step but never again (unless it is reset to another value)
3531e35cf81dSBarry Smith 
3532dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3533e35cf81dSBarry Smith @*/
3534d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3535d71ae5a4SJacob Faibussowitsch {
3536e35cf81dSBarry Smith   PetscFunctionBegin;
35370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35385f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35395f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3540c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3541e35cf81dSBarry Smith   snes->lagjacobian = lag;
35423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3543e35cf81dSBarry Smith }
3544e35cf81dSBarry Smith 
3545e35cf81dSBarry Smith /*@
3546f6dfbefdSBarry Smith    SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3547e35cf81dSBarry Smith 
35483f9fe445SBarry Smith    Not Collective
3549e35cf81dSBarry Smith 
3550e35cf81dSBarry Smith    Input Parameter:
3551f6dfbefdSBarry Smith .  snes - the `SNES` context
3552e35cf81dSBarry Smith 
3553e35cf81dSBarry Smith    Output Parameter:
3554e35cf81dSBarry 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
3555e35cf81dSBarry Smith          the Jacobian is built etc.
3556e35cf81dSBarry Smith 
3557dc4c0fb0SBarry Smith    Level: intermediate
3558dc4c0fb0SBarry Smith 
3559e35cf81dSBarry Smith    Notes:
3560e35cf81dSBarry Smith    The default is 1
3561f6dfbefdSBarry Smith 
3562f6dfbefdSBarry Smith    The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3563e35cf81dSBarry Smith 
3564dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3565e35cf81dSBarry Smith 
3566e35cf81dSBarry Smith @*/
3567d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3568d71ae5a4SJacob Faibussowitsch {
3569e35cf81dSBarry Smith   PetscFunctionBegin;
35700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3571e35cf81dSBarry Smith   *lag = snes->lagjacobian;
35723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3573e35cf81dSBarry Smith }
3574e35cf81dSBarry Smith 
357537ec4e1aSPeter Brune /*@
3576f6dfbefdSBarry Smith    SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
357737ec4e1aSPeter Brune 
3578c3339decSBarry Smith    Logically collective
357937ec4e1aSPeter Brune 
3580d8d19677SJose E. Roman    Input Parameters:
3581f6dfbefdSBarry Smith +  snes - the `SNES` context
35829d7e2deaSPeter Brune -   flg - jacobian lagging persists if true
358337ec4e1aSPeter Brune 
358437ec4e1aSPeter Brune    Options Database Keys:
35853d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
35863d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
35873d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
35883d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
35893d5a8a6aSBarry Smith 
3590dc4c0fb0SBarry Smith    Level: advanced
3591dc4c0fb0SBarry Smith 
359295452b02SPatrick Sanan    Notes:
3593f6dfbefdSBarry Smith     Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3594f6dfbefdSBarry Smith 
359595452b02SPatrick Sanan     This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
359637ec4e1aSPeter Brune    several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
359737ec4e1aSPeter Brune    timesteps may present huge efficiency gains.
359837ec4e1aSPeter Brune 
3599dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagJacobianPersists()`
360037ec4e1aSPeter Brune @*/
3601d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3602d71ae5a4SJacob Faibussowitsch {
360337ec4e1aSPeter Brune   PetscFunctionBegin;
360437ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
360537ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
360637ec4e1aSPeter Brune   snes->lagjac_persist = flg;
36073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
360837ec4e1aSPeter Brune }
360937ec4e1aSPeter Brune 
361037ec4e1aSPeter Brune /*@
3611d8e291bfSBarry Smith    SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
361237ec4e1aSPeter Brune 
3613c3339decSBarry Smith    Logically Collective
361437ec4e1aSPeter Brune 
3615d8d19677SJose E. Roman    Input Parameters:
3616f6dfbefdSBarry Smith +  snes - the `SNES` context
36179d7e2deaSPeter Brune -   flg - preconditioner lagging persists if true
361837ec4e1aSPeter Brune 
361937ec4e1aSPeter Brune    Options Database Keys:
36203d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
36213d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
36223d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
36233d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
362437ec4e1aSPeter Brune 
3625dc4c0fb0SBarry Smith    Level: developer
3626dc4c0fb0SBarry Smith 
362795452b02SPatrick Sanan    Notes:
3628f6dfbefdSBarry Smith     Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3629f6dfbefdSBarry Smith 
363095452b02SPatrick Sanan    This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
363137ec4e1aSPeter Brune    by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
363237ec4e1aSPeter Brune    several timesteps may present huge efficiency gains.
363337ec4e1aSPeter Brune 
3634dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
363537ec4e1aSPeter Brune @*/
3636d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3637d71ae5a4SJacob Faibussowitsch {
363837ec4e1aSPeter Brune   PetscFunctionBegin;
363937ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
364037ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
364137ec4e1aSPeter Brune   snes->lagpre_persist = flg;
36423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
364337ec4e1aSPeter Brune }
364437ec4e1aSPeter Brune 
36459b94acceSBarry Smith /*@
3646f6dfbefdSBarry Smith    SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3647be5caee7SBarry Smith 
3648c3339decSBarry Smith    Logically Collective
3649be5caee7SBarry Smith 
3650be5caee7SBarry Smith    Input Parameters:
3651f6dfbefdSBarry Smith +  snes - the `SNES` context
3652f6dfbefdSBarry Smith -  force - `PETSC_TRUE` require at least one iteration
3653be5caee7SBarry Smith 
3654f6dfbefdSBarry Smith    Options Database Key:
3655be5caee7SBarry Smith .    -snes_force_iteration <force> - Sets forcing an iteration
3656be5caee7SBarry Smith 
3657dc4c0fb0SBarry Smith    Level: intermediate
3658dc4c0fb0SBarry Smith 
3659f6dfbefdSBarry Smith    Note:
3660f6dfbefdSBarry Smith    This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3661be5caee7SBarry Smith 
3662dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3663be5caee7SBarry Smith @*/
3664d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3665d71ae5a4SJacob Faibussowitsch {
3666be5caee7SBarry Smith   PetscFunctionBegin;
3667be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3668be5caee7SBarry Smith   snes->forceiteration = force;
36693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3670be5caee7SBarry Smith }
3671be5caee7SBarry Smith 
367285216dc7SFande Kong /*@
3673f6dfbefdSBarry Smith    SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
367485216dc7SFande Kong 
3675c3339decSBarry Smith    Logically Collective
367685216dc7SFande Kong 
367785216dc7SFande Kong    Input Parameters:
3678f6dfbefdSBarry Smith .  snes - the `SNES` context
367985216dc7SFande Kong 
368085216dc7SFande Kong    Output Parameter:
3681dc4c0fb0SBarry Smith .  force - `PETSC_TRUE` requires at least one iteration.
368285216dc7SFande Kong 
368306dd6b0eSSatish Balay    Level: intermediate
368406dd6b0eSSatish Balay 
3685dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
368685216dc7SFande Kong @*/
3687d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3688d71ae5a4SJacob Faibussowitsch {
368985216dc7SFande Kong   PetscFunctionBegin;
369085216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
369185216dc7SFande Kong   *force = snes->forceiteration;
36923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
369385216dc7SFande Kong }
3694be5caee7SBarry Smith 
3695be5caee7SBarry Smith /*@
3696f6dfbefdSBarry Smith    SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
36979b94acceSBarry Smith 
3698c3339decSBarry Smith    Logically Collective
3699c7afd0dbSLois Curfman McInnes 
37009b94acceSBarry Smith    Input Parameters:
3701f6dfbefdSBarry Smith +  snes - the `SNES` context
370270441072SBarry Smith .  abstol - absolute convergence tolerance
370333174efeSLois Curfman McInnes .  rtol - relative convergence tolerance
37045358d0d4SBarry Smith .  stol -  convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3705f6dfbefdSBarry Smith .  maxit - maximum number of iterations, default 50.
3706f6dfbefdSBarry Smith -  maxf - maximum number of function evaluations (-1 indicates no limit), default 1000
3707fee21e36SBarry Smith 
370833174efeSLois Curfman McInnes    Options Database Keys:
370970441072SBarry Smith +    -snes_atol <abstol> - Sets abstol
3710c7afd0dbSLois Curfman McInnes .    -snes_rtol <rtol> - Sets rtol
3711c7afd0dbSLois Curfman McInnes .    -snes_stol <stol> - Sets stol
3712c7afd0dbSLois Curfman McInnes .    -snes_max_it <maxit> - Sets maxit
3713c7afd0dbSLois Curfman McInnes -    -snes_max_funcs <maxf> - Sets maxf
37149b94acceSBarry Smith 
371536851e7fSLois Curfman McInnes    Level: intermediate
371636851e7fSLois Curfman McInnes 
3717dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
37189b94acceSBarry Smith @*/
3719d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3720d71ae5a4SJacob Faibussowitsch {
37213a40ed3dSBarry Smith   PetscFunctionBegin;
37220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3723c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3724c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3725c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3726c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3727c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3728c5eb9154SBarry Smith 
372913bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
37305f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3731ab54825eSJed Brown     snes->abstol = abstol;
3732ab54825eSJed Brown   }
373313bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
37345f80ce2aSJacob 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);
3735ab54825eSJed Brown     snes->rtol = rtol;
3736ab54825eSJed Brown   }
373713bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
37385f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3739c60f73f4SPeter Brune     snes->stol = stol;
3740ab54825eSJed Brown   }
3741ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
374263a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3743ab54825eSJed Brown     snes->max_its = maxit;
3744ab54825eSJed Brown   }
3745ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
374663a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3747ab54825eSJed Brown     snes->max_funcs = maxf;
3748ab54825eSJed Brown   }
374988976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
37503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37519b94acceSBarry Smith }
37529b94acceSBarry Smith 
3753e4d06f11SPatrick Farrell /*@
3754f6dfbefdSBarry Smith    SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3755e4d06f11SPatrick Farrell 
3756c3339decSBarry Smith    Logically Collective
3757e4d06f11SPatrick Farrell 
3758e4d06f11SPatrick Farrell    Input Parameters:
3759f6dfbefdSBarry Smith +  snes - the `SNES` context
3760f6dfbefdSBarry Smith -  divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3761e4d06f11SPatrick Farrell 
3762f6dfbefdSBarry Smith    Options Database Key:
3763dc4c0fb0SBarry Smith .    -snes_divergence_tolerance <divtol> - Sets `divtol`
3764e4d06f11SPatrick Farrell 
3765e4d06f11SPatrick Farrell    Level: intermediate
3766e4d06f11SPatrick Farrell 
3767dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3768e4d06f11SPatrick Farrell @*/
3769d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3770d71ae5a4SJacob Faibussowitsch {
3771e4d06f11SPatrick Farrell   PetscFunctionBegin;
3772e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3773e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3774e4d06f11SPatrick Farrell 
377513bcc0bdSJacob Faibussowitsch   if (divtol != (PetscReal)PETSC_DEFAULT) {
3776e4d06f11SPatrick Farrell     snes->divtol = divtol;
37779371c9d4SSatish Balay   } else {
3778e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3779e4d06f11SPatrick Farrell   }
37803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3781e4d06f11SPatrick Farrell }
3782e4d06f11SPatrick Farrell 
37839b94acceSBarry Smith /*@
378433174efeSLois Curfman McInnes    SNESGetTolerances - Gets various parameters used in convergence tests.
378533174efeSLois Curfman McInnes 
3786c7afd0dbSLois Curfman McInnes    Not Collective
3787c7afd0dbSLois Curfman McInnes 
378833174efeSLois Curfman McInnes    Input Parameters:
3789f6dfbefdSBarry Smith +  snes - the `SNES` context
379085385478SLisandro Dalcin .  atol - absolute convergence tolerance
379133174efeSLois Curfman McInnes .  rtol - relative convergence tolerance
379233174efeSLois Curfman McInnes .  stol -  convergence tolerance in terms of the norm
379333174efeSLois Curfman McInnes            of the change in the solution between steps
379433174efeSLois Curfman McInnes .  maxit - maximum number of iterations
3795c7afd0dbSLois Curfman McInnes -  maxf - maximum number of function evaluations
3796fee21e36SBarry Smith 
379736851e7fSLois Curfman McInnes    Level: intermediate
379836851e7fSLois Curfman McInnes 
3799dc4c0fb0SBarry Smith    Note:
3800dc4c0fb0SBarry Smith    The user can specify `NULL` for any parameter that is not needed.
3801dc4c0fb0SBarry Smith 
3802dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTolerances()`
380333174efeSLois Curfman McInnes @*/
3804d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3805d71ae5a4SJacob Faibussowitsch {
38063a40ed3dSBarry Smith   PetscFunctionBegin;
38070700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
380885385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
380933174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3810c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
381133174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
381233174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
38133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
381433174efeSLois Curfman McInnes }
381533174efeSLois Curfman McInnes 
3816e4d06f11SPatrick Farrell /*@
3817e4d06f11SPatrick Farrell    SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3818e4d06f11SPatrick Farrell 
3819e4d06f11SPatrick Farrell    Not Collective
3820e4d06f11SPatrick Farrell 
3821e4d06f11SPatrick Farrell    Input Parameters:
3822f6dfbefdSBarry Smith +  snes - the `SNES` context
3823e4d06f11SPatrick Farrell -  divtol - divergence tolerance
3824e4d06f11SPatrick Farrell 
3825e4d06f11SPatrick Farrell    Level: intermediate
3826e4d06f11SPatrick Farrell 
3827dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetDivergenceTolerance()`
3828e4d06f11SPatrick Farrell @*/
3829d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3830d71ae5a4SJacob Faibussowitsch {
3831e4d06f11SPatrick Farrell   PetscFunctionBegin;
3832e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3833e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
38343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3835e4d06f11SPatrick Farrell }
3836e4d06f11SPatrick Farrell 
383733174efeSLois Curfman McInnes /*@
38389b94acceSBarry Smith    SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
38399b94acceSBarry Smith 
3840c3339decSBarry Smith    Logically Collective
3841fee21e36SBarry Smith 
3842c7afd0dbSLois Curfman McInnes    Input Parameters:
3843f6dfbefdSBarry Smith +  snes - the `SNES` context
3844c7afd0dbSLois Curfman McInnes -  tol - tolerance
3845c7afd0dbSLois Curfman McInnes 
38469b94acceSBarry Smith    Options Database Key:
38474a221d59SStefano Zampini .  -snes_tr_tol <tol> - Sets tol
38489b94acceSBarry Smith 
384936851e7fSLois Curfman McInnes    Level: intermediate
385036851e7fSLois Curfman McInnes 
38514a221d59SStefano Zampini .seealso: [](chapter_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
38529b94acceSBarry Smith @*/
3853d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3854d71ae5a4SJacob Faibussowitsch {
38553a40ed3dSBarry Smith   PetscFunctionBegin;
38560700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3857c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
38589b94acceSBarry Smith   snes->deltatol = tol;
38593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38609b94acceSBarry Smith }
38619b94acceSBarry Smith 
38626ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
38636ba87a44SLisandro Dalcin 
3864d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3865d71ae5a4SJacob Faibussowitsch {
3866b271bb04SBarry Smith   PetscDrawLG      lg;
3867b271bb04SBarry Smith   PetscReal        x, y, per;
3868b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3869b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3870b271bb04SBarry Smith   PetscDraw        draw;
3871b271bb04SBarry Smith 
3872459f5d12SBarry Smith   PetscFunctionBegin;
38734d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
38749566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
38759566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38769566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38779566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3878b271bb04SBarry Smith   x = (PetscReal)n;
387977b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
388094c9c6d3SKarl Rupp   else y = -15.0;
38819566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38826934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38839566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38849566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3885b271bb04SBarry Smith   }
3886b271bb04SBarry Smith 
38879566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
38889566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38899566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38909566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "% elemts > .2*max elemt"));
38919566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3892b271bb04SBarry Smith   x = (PetscReal)n;
3893b271bb04SBarry Smith   y = 100.0 * per;
38949566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38956934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38969566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38979566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3898b271bb04SBarry Smith   }
3899b271bb04SBarry Smith 
39009566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
39019371c9d4SSatish Balay   if (!n) {
39029371c9d4SSatish Balay     prev = rnorm;
39039371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
39049371c9d4SSatish Balay   }
39059566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39069566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3907b271bb04SBarry Smith   x = (PetscReal)n;
3908b271bb04SBarry Smith   y = (prev - rnorm) / prev;
39099566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39106934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39119566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39129566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3913b271bb04SBarry Smith   }
3914b271bb04SBarry Smith 
39159566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
39169566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39179566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39189566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3919b271bb04SBarry Smith   x = (PetscReal)n;
3920b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3921b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
39229566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3923b271bb04SBarry Smith   }
39246934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39259566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39269566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3927b271bb04SBarry Smith   }
3928b271bb04SBarry Smith   prev = rnorm;
39293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3930b271bb04SBarry Smith }
3931b271bb04SBarry Smith 
3932228d79bcSJed Brown /*@
3933228d79bcSJed Brown    SNESMonitor - runs the user provided monitor routines, if they exist
3934228d79bcSJed Brown 
3935c3339decSBarry Smith    Collective
3936228d79bcSJed Brown 
3937228d79bcSJed Brown    Input Parameters:
3938f6dfbefdSBarry Smith +  snes - nonlinear solver context obtained from `SNESCreate()`
3939228d79bcSJed Brown .  iter - iteration number
3940228d79bcSJed Brown -  rnorm - relative norm of the residual
3941228d79bcSJed Brown 
3942dc4c0fb0SBarry Smith    Level: developer
3943dc4c0fb0SBarry Smith 
3944f6dfbefdSBarry Smith    Note:
3945f6dfbefdSBarry Smith    This routine is called by the `SNES` implementations.
3946228d79bcSJed Brown    It does not typically need to be called by the user.
3947228d79bcSJed Brown 
3948dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESMonitorSet()`
3949228d79bcSJed Brown @*/
3950d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
3951d71ae5a4SJacob Faibussowitsch {
39527a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
39537a03ce2fSLisandro Dalcin 
39547a03ce2fSLisandro Dalcin   PetscFunctionBegin;
39559566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
395648a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
39579566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
39583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39597a03ce2fSLisandro Dalcin }
39607a03ce2fSLisandro Dalcin 
39619b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
39629b94acceSBarry Smith 
3963bf388a1fSBarry Smith /*MC
3964f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
3965bf388a1fSBarry Smith 
3966bf388a1fSBarry Smith      Synopsis:
3967aaa7dc30SBarry Smith      #include <petscsnes.h>
3968bf388a1fSBarry Smith $    PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx)
3969bf388a1fSBarry Smith 
3970c3339decSBarry Smith      Collective
39711843f636SBarry Smith 
39721843f636SBarry Smith     Input Parameters:
3973f6dfbefdSBarry Smith +    snes - the `SNES` context
3974bf388a1fSBarry Smith .    its - iteration number
3975bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
3976bf388a1fSBarry Smith -    mctx - [optional] monitoring context
3977bf388a1fSBarry Smith 
3978878cb397SSatish Balay    Level: advanced
3979878cb397SSatish Balay 
3980dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
3981bf388a1fSBarry Smith M*/
3982bf388a1fSBarry Smith 
39839b94acceSBarry Smith /*@C
3984a6570f20SBarry Smith    SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
39859b94acceSBarry Smith    iteration of the nonlinear solver to display the iteration's
39869b94acceSBarry Smith    progress.
39879b94acceSBarry Smith 
3988c3339decSBarry Smith    Logically Collective
3989fee21e36SBarry Smith 
3990c7afd0dbSLois Curfman McInnes    Input Parameters:
3991f6dfbefdSBarry Smith +  snes - the `SNES` context
3992*20f4b53cSBarry Smith .  f - the monitor function,  for the calling sequence see `SNESMonitorFunction`
3993b8a78c4aSBarry Smith .  mctx - [optional] user-defined context for private data for the
3994dc4c0fb0SBarry Smith           monitor routine (use `NULL` if no context is desired)
3995dc4c0fb0SBarry Smith -  monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
39969b94acceSBarry Smith 
39979665c990SLois Curfman McInnes    Options Database Keys:
3998f6dfbefdSBarry Smith +    -snes_monitor        - sets `SNESMonitorDefault()`
3999798534f6SMatthew G. Knepley .    -snes_monitor draw::draw_lg - sets line graph monitor,
4000dc4c0fb0SBarry Smith -    -snes_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `SNESMonitorSet()`, but does not cancel those set via
4001c7afd0dbSLois Curfman McInnes                             the options database.
40029665c990SLois Curfman McInnes 
4003dc4c0fb0SBarry Smith    Level: intermediate
4004dc4c0fb0SBarry Smith 
4005f6dfbefdSBarry Smith    Note:
40066bc08f3fSLois Curfman McInnes    Several different monitoring routines may be set by calling
4007f6dfbefdSBarry Smith    `SNESMonitorSet()` multiple times; all will be called in the
40086bc08f3fSLois Curfman McInnes    order in which they were set.
4009639f9d9dSBarry Smith 
4010f6dfbefdSBarry Smith    Fortran Note:
4011f6dfbefdSBarry Smith    Only a single monitor function can be set for each `SNES` object
4012025f1a04SBarry Smith 
4013dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
40149b94acceSBarry Smith @*/
4015d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4016d71ae5a4SJacob Faibussowitsch {
4017b90d0a6eSBarry Smith   PetscInt  i;
401878064530SBarry Smith   PetscBool identical;
4019b90d0a6eSBarry Smith 
40203a40ed3dSBarry Smith   PetscFunctionBegin;
40210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4022b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
40239566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
40243ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4025649052a6SBarry Smith   }
40265f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
40276e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4028b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4029639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
40303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40319b94acceSBarry Smith }
40329b94acceSBarry Smith 
4033a278d85bSSatish Balay /*@
4034f6dfbefdSBarry Smith    SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
40355cd90555SBarry Smith 
4036c3339decSBarry Smith    Logically Collective
4037c7afd0dbSLois Curfman McInnes 
40385cd90555SBarry Smith    Input Parameters:
4039f6dfbefdSBarry Smith .  snes - the `SNES` context
40405cd90555SBarry Smith 
40411a480d89SAdministrator    Options Database Key:
4042a6570f20SBarry Smith .  -snes_monitor_cancel - cancels all monitors that have been hardwired
4043dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4044c7afd0dbSLois Curfman McInnes     set via the options database
40455cd90555SBarry Smith 
4046dc4c0fb0SBarry Smith    Level: intermediate
4047dc4c0fb0SBarry Smith 
4048f6dfbefdSBarry Smith    Note:
4049f6dfbefdSBarry Smith    There is no way to clear one specific monitor from a `SNES` object.
40505cd90555SBarry Smith 
4051dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
40525cd90555SBarry Smith @*/
4053d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4054d71ae5a4SJacob Faibussowitsch {
4055d952e501SBarry Smith   PetscInt i;
4056d952e501SBarry Smith 
40575cd90555SBarry Smith   PetscFunctionBegin;
40580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4059d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
406048a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4061d952e501SBarry Smith   }
40625cd90555SBarry Smith   snes->numbermonitors = 0;
40633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40645cd90555SBarry Smith }
40655cd90555SBarry Smith 
4066bf388a1fSBarry Smith /*MC
4067bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4068bf388a1fSBarry Smith 
4069bf388a1fSBarry Smith      Synopsis:
4070aaa7dc30SBarry Smith      #include <petscsnes.h>
4071bf388a1fSBarry Smith $     PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx)
4072bf388a1fSBarry Smith 
4073c3339decSBarry Smith      Collective
40741843f636SBarry Smith 
40751843f636SBarry Smith     Input Parameters:
4076f6dfbefdSBarry Smith +    snes - the `SNES` context
4077bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4078bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4079bf388a1fSBarry Smith .    gnorm - 2-norm of current step
40801843f636SBarry Smith .    f - 2-norm of function
40811843f636SBarry Smith -    cctx - [optional] convergence context
40821843f636SBarry Smith 
40831843f636SBarry Smith     Output Parameter:
40841843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4085bf388a1fSBarry Smith 
4086878cb397SSatish Balay    Level: intermediate
4087bf388a1fSBarry Smith 
4088dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4089bf388a1fSBarry Smith M*/
4090bf388a1fSBarry Smith 
40919b94acceSBarry Smith /*@C
40929b94acceSBarry Smith    SNESSetConvergenceTest - Sets the function that is to be used
40939b94acceSBarry Smith    to test for convergence of the nonlinear iterative solution.
40949b94acceSBarry Smith 
4095c3339decSBarry Smith    Logically Collective
4096fee21e36SBarry Smith 
4097c7afd0dbSLois Curfman McInnes    Input Parameters:
4098f6dfbefdSBarry Smith +  snes - the `SNES` context
4099f6dfbefdSBarry Smith .  `SNESConvergenceTestFunction` - routine to test for convergence
4100dc4c0fb0SBarry Smith .  cctx - [optional] context for private data for the convergence routine  (may be `NULL`)
4101dc4c0fb0SBarry Smith -  destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
41029b94acceSBarry Smith 
410336851e7fSLois Curfman McInnes    Level: advanced
410436851e7fSLois Curfman McInnes 
4105dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
41069b94acceSBarry Smith @*/
4107d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4108d71ae5a4SJacob Faibussowitsch {
41093a40ed3dSBarry Smith   PetscFunctionBegin;
41100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4111e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
41121baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4113bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
41147f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
411585385478SLisandro Dalcin   snes->cnvP                  = cctx;
41163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41179b94acceSBarry Smith }
41189b94acceSBarry Smith 
411952baeb72SSatish Balay /*@
4120f6dfbefdSBarry Smith    SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4121184914b5SBarry Smith 
4122184914b5SBarry Smith    Not Collective
4123184914b5SBarry Smith 
4124184914b5SBarry Smith    Input Parameter:
4125f6dfbefdSBarry Smith .  snes - the `SNES` context
4126184914b5SBarry Smith 
4127184914b5SBarry Smith    Output Parameter:
4128f6dfbefdSBarry Smith .  reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4129184914b5SBarry Smith 
4130f6dfbefdSBarry Smith    Options Database Key:
41316a4d7782SBarry Smith .   -snes_converged_reason - prints the reason to standard out
41326a4d7782SBarry Smith 
4133184914b5SBarry Smith    Level: intermediate
4134184914b5SBarry Smith 
4135f6dfbefdSBarry Smith    Note:
4136f6dfbefdSBarry Smith     Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4137184914b5SBarry Smith 
4138dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4139184914b5SBarry Smith @*/
4140d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4141d71ae5a4SJacob Faibussowitsch {
4142184914b5SBarry Smith   PetscFunctionBegin;
41430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41444482741eSBarry Smith   PetscValidPointer(reason, 2);
4145184914b5SBarry Smith   *reason = snes->reason;
41463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4147184914b5SBarry Smith }
4148184914b5SBarry Smith 
4149c4421ceaSFande Kong /*@C
4150f6dfbefdSBarry Smith    SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4151c4421ceaSFande Kong 
4152c4421ceaSFande Kong    Not Collective
4153c4421ceaSFande Kong 
4154c4421ceaSFande Kong    Input Parameter:
4155f6dfbefdSBarry Smith .  snes - the `SNES` context
4156c4421ceaSFande Kong 
4157c4421ceaSFande Kong    Output Parameter:
4158dc4c0fb0SBarry Smith .  strreason - a human readable string that describes `SNES` converged reason
4159c4421ceaSFande Kong 
416099c90e12SSatish Balay    Level: beginner
4161c4421ceaSFande Kong 
4162dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetConvergedReason()`
4163c4421ceaSFande Kong @*/
4164d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4165d71ae5a4SJacob Faibussowitsch {
4166c4421ceaSFande Kong   PetscFunctionBegin;
4167c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4168dadcf809SJacob Faibussowitsch   PetscValidPointer(strreason, 2);
4169c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
41703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4171c4421ceaSFande Kong }
4172c4421ceaSFande Kong 
417333866048SMatthew G. Knepley /*@
4174f6dfbefdSBarry Smith    SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
417533866048SMatthew G. Knepley 
417633866048SMatthew G. Knepley    Not Collective
417733866048SMatthew G. Knepley 
417833866048SMatthew G. Knepley    Input Parameters:
4179f6dfbefdSBarry Smith +  snes - the `SNES` context
4180f6dfbefdSBarry Smith -  reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
418133866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
418233866048SMatthew G. Knepley 
4183f6dfbefdSBarry Smith    Level: developer
4184f6dfbefdSBarry Smith 
4185f6dfbefdSBarry Smith    Developer Note:
4186f6dfbefdSBarry Smith    Called inside the various `SNESSolve()` implementations
418733866048SMatthew G. Knepley 
4188dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
418933866048SMatthew G. Knepley @*/
4190d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4191d71ae5a4SJacob Faibussowitsch {
419233866048SMatthew G. Knepley   PetscFunctionBegin;
419333866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
419433866048SMatthew G. Knepley   snes->reason = reason;
41953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
419633866048SMatthew G. Knepley }
419733866048SMatthew G. Knepley 
4198c9005455SLois Curfman McInnes /*@
4199c9005455SLois Curfman McInnes    SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
4200c9005455SLois Curfman McInnes 
4201c3339decSBarry Smith    Logically Collective
4202fee21e36SBarry Smith 
4203c7afd0dbSLois Curfman McInnes    Input Parameters:
4204f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
42058c7482ecSBarry Smith .  a   - array to hold history, this array will contain the function norms computed at each step
4206cd5578b5SBarry Smith .  its - integer array holds the number of linear iterations for each solve.
4207758f92a0SBarry Smith .  na  - size of a and its
4208f6dfbefdSBarry Smith -  reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4209758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4210c7afd0dbSLois Curfman McInnes 
4211dc4c0fb0SBarry Smith    Level: intermediate
4212dc4c0fb0SBarry Smith 
4213308dcc3eSBarry Smith    Notes:
4214dc4c0fb0SBarry Smith    If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4215308dcc3eSBarry Smith    default array of length 10000 is allocated.
4216308dcc3eSBarry Smith 
4217c9005455SLois Curfman McInnes    This routine is useful, e.g., when running a code for purposes
4218c9005455SLois Curfman McInnes    of accurate performance monitoring, when no I/O should be done
4219c9005455SLois Curfman McInnes    during the section of code that is being timed.
4220c9005455SLois Curfman McInnes 
4221dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4222c9005455SLois Curfman McInnes @*/
4223d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4224d71ae5a4SJacob Faibussowitsch {
42253a40ed3dSBarry Smith   PetscFunctionBegin;
42260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4227064a246eSJacob Faibussowitsch   if (a) PetscValidRealPointer(a, 2);
4228a562a398SLisandro Dalcin   if (its) PetscValidIntPointer(its, 3);
42297a1ec6d4SBarry Smith   if (!a) {
4230308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
42319566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4232071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4233308dcc3eSBarry Smith   }
4234c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4235758f92a0SBarry Smith   snes->conv_hist_its   = its;
4236115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4237a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4238758f92a0SBarry Smith   snes->conv_hist_reset = reset;
42393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4240758f92a0SBarry Smith }
4241758f92a0SBarry Smith 
4242d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4243c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4244c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
424599e0435eSBarry Smith 
4246d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4247d71ae5a4SJacob Faibussowitsch {
4248308dcc3eSBarry Smith   mxArray   *mat;
4249308dcc3eSBarry Smith   PetscInt   i;
4250308dcc3eSBarry Smith   PetscReal *ar;
4251308dcc3eSBarry Smith 
4252308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4253308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4254f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
425511cc89d2SBarry Smith   return mat;
4256308dcc3eSBarry Smith }
4257308dcc3eSBarry Smith #endif
4258308dcc3eSBarry Smith 
42590c4c9dddSBarry Smith /*@C
4260758f92a0SBarry Smith    SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
4261758f92a0SBarry Smith 
42623f9fe445SBarry Smith    Not Collective
4263758f92a0SBarry Smith 
4264758f92a0SBarry Smith    Input Parameter:
4265f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
4266758f92a0SBarry Smith 
4267758f92a0SBarry Smith    Output Parameters:
4268f6dfbefdSBarry Smith +  a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4269758f92a0SBarry Smith .  its - integer array holds the number of linear iterations (or
4270758f92a0SBarry Smith          negative if not converged) for each solve.
4271*20f4b53cSBarry Smith -  na  - size of `a` and `its`
4272758f92a0SBarry Smith 
4273dc4c0fb0SBarry Smith    Level: intermediate
4274dc4c0fb0SBarry Smith 
4275*20f4b53cSBarry Smith    Note:
4276*20f4b53cSBarry Smith    This routine is useful, e.g., when running a code for purposes
4277*20f4b53cSBarry Smith    of accurate performance monitoring, when no I/O should be done
4278*20f4b53cSBarry Smith    during the section of code that is being timed.
4279*20f4b53cSBarry Smith 
4280*20f4b53cSBarry Smith    Fortran Note:
4281758f92a0SBarry Smith     The calling sequence for this routine in Fortran is
4282dc4c0fb0SBarry Smith .vb
4283dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4284dc4c0fb0SBarry Smith .ve
4285758f92a0SBarry Smith 
4286dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4287758f92a0SBarry Smith @*/
4288d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4289d71ae5a4SJacob Faibussowitsch {
4290758f92a0SBarry Smith   PetscFunctionBegin;
42910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4292758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4293758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4294115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
42953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4296c9005455SLois Curfman McInnes }
4297c9005455SLois Curfman McInnes 
4298ac226902SBarry Smith /*@C
429976b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4300eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
43017e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
430276b2cf59SMatthew Knepley 
4303c3339decSBarry Smith   Logically Collective
430476b2cf59SMatthew Knepley 
430576b2cf59SMatthew Knepley   Input Parameters:
4306a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4307a2b725a8SWilliam Gropp - func - The function
430876b2cf59SMatthew Knepley 
4309*20f4b53cSBarry Smith   Calling sequence of `func`:
4310*20f4b53cSBarry Smith $ PetscErrorCode func(SNES snes, PetscInt step);
4311*20f4b53cSBarry Smith + snes - the nonlinear solver context
4312*20f4b53cSBarry Smith - step - The current step of the iteration
431376b2cf59SMatthew Knepley 
4314fe97e370SBarry Smith   Level: advanced
4315fe97e370SBarry Smith 
43166b7fb656SBarry Smith   Note:
4317f6dfbefdSBarry 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
4318f6dfbefdSBarry Smith      to `SNESSetFunction()`, or `SNESSetPicard()`
4319fe97e370SBarry Smith      This is not used by most users.
432076b2cf59SMatthew Knepley 
43216b7fb656SBarry 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.
43226b7fb656SBarry Smith 
4323dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESSolve()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4324db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
432576b2cf59SMatthew Knepley @*/
4326d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
4327d71ae5a4SJacob Faibussowitsch {
432876b2cf59SMatthew Knepley   PetscFunctionBegin;
43290700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4330e7788613SBarry Smith   snes->ops->update = func;
43313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
433276b2cf59SMatthew Knepley }
433376b2cf59SMatthew Knepley 
43349b94acceSBarry Smith /*
43359b94acceSBarry Smith    SNESScaleStep_Private - Scales a step so that its length is less than the
43369b94acceSBarry Smith    positive parameter delta.
43379b94acceSBarry Smith 
43389b94acceSBarry Smith     Input Parameters:
4339f6dfbefdSBarry Smith +   snes - the `SNES` context
43409b94acceSBarry Smith .   y - approximate solution of linear system
43419b94acceSBarry Smith .   fnorm - 2-norm of current function
4342c7afd0dbSLois Curfman McInnes -   delta - trust region size
43439b94acceSBarry Smith 
43449b94acceSBarry Smith     Output Parameters:
4345c7afd0dbSLois Curfman McInnes +   gpnorm - predicted function norm at the new point, assuming local
43469b94acceSBarry Smith     linearization.  The value is zero if the step lies within the trust
43479b94acceSBarry Smith     region, and exceeds zero otherwise.
4348c7afd0dbSLois Curfman McInnes -   ynorm - 2-norm of the step
43499b94acceSBarry Smith 
4350f6dfbefdSBarry Smith     Level: developer
43519b94acceSBarry Smith 
4352f6dfbefdSBarry Smith     Note:
4353f6dfbefdSBarry Smith     For non-trust region methods such as `SNESNEWTONLS`, the parameter delta
4354f6dfbefdSBarry Smith     is set to be the maximum allowable step size.
43559b94acceSBarry Smith */
4356d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESScaleStep_Private(SNES snes, Vec y, PetscReal *fnorm, PetscReal *delta, PetscReal *gpnorm, PetscReal *ynorm)
4357d71ae5a4SJacob Faibussowitsch {
4358064f8208SBarry Smith   PetscReal   nrm;
4359ea709b57SSatish Balay   PetscScalar cnorm;
43603a40ed3dSBarry Smith 
43613a40ed3dSBarry Smith   PetscFunctionBegin;
43620700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43630700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 2);
4364c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 2);
4365184914b5SBarry Smith 
43669566063dSJacob Faibussowitsch   PetscCall(VecNorm(y, NORM_2, &nrm));
4367064f8208SBarry Smith   if (nrm > *delta) {
4368064f8208SBarry Smith     nrm     = *delta / nrm;
4369064f8208SBarry Smith     *gpnorm = (1.0 - nrm) * (*fnorm);
4370064f8208SBarry Smith     cnorm   = nrm;
43719566063dSJacob Faibussowitsch     PetscCall(VecScale(y, cnorm));
43729b94acceSBarry Smith     *ynorm = *delta;
43739b94acceSBarry Smith   } else {
43749b94acceSBarry Smith     *gpnorm = 0.0;
4375064f8208SBarry Smith     *ynorm  = nrm;
43769b94acceSBarry Smith   }
43773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43789b94acceSBarry Smith }
43799b94acceSBarry Smith 
438091f3e32bSBarry Smith /*@C
4381f6dfbefdSBarry Smith    SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
43822a359c20SBarry Smith 
4383c3339decSBarry Smith    Collective
43842a359c20SBarry Smith 
43852a359c20SBarry Smith    Parameter:
4386f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
43872a359c20SBarry Smith -  viewer - the viewer to display the reason
43882a359c20SBarry Smith 
43892a359c20SBarry Smith    Options Database Keys:
4390ee300463SSatish Balay +  -snes_converged_reason - print reason for converged or diverged, also prints number of iterations
4391ee300463SSatish Balay -  -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4392eafd5ff0SAlex Lindsay 
4393f6dfbefdSBarry Smith   Note:
4394f6dfbefdSBarry Smith      To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4395f6dfbefdSBarry Smith      use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
43962a359c20SBarry Smith 
43972a359c20SBarry Smith    Level: beginner
43982a359c20SBarry Smith 
4399dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4400f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4401f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4402db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
44032a359c20SBarry Smith @*/
4404d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4405d71ae5a4SJacob Faibussowitsch {
440675cca76cSMatthew G. Knepley   PetscViewerFormat format;
44072a359c20SBarry Smith   PetscBool         isAscii;
44082a359c20SBarry Smith 
44092a359c20SBarry Smith   PetscFunctionBegin;
441019a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
44119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
44122a359c20SBarry Smith   if (isAscii) {
44139566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
44149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
441575cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
441675cca76cSMatthew G. Knepley       DM       dm;
441775cca76cSMatthew G. Knepley       Vec      u;
441875cca76cSMatthew G. Knepley       PetscDS  prob;
441975cca76cSMatthew G. Knepley       PetscInt Nf, f;
442095cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
442195cbbfd3SMatthew G. Knepley       void    **exactCtx;
442275cca76cSMatthew G. Knepley       PetscReal error;
442375cca76cSMatthew G. Knepley 
44249566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
44259566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
44269566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
44279566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
44289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
44299566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
44309566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
44319566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
44329566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
443363a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
443475cca76cSMatthew G. Knepley     }
4435eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
44362a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
443763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
44382a359c20SBarry Smith       } else {
443963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44402a359c20SBarry Smith       }
4441eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
44422a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
444363a3b9bcSJacob 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));
44442a359c20SBarry Smith       } else {
444563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44462a359c20SBarry Smith       }
44472a359c20SBarry Smith     }
44489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
44492a359c20SBarry Smith   }
44503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44512a359c20SBarry Smith }
44522a359c20SBarry Smith 
4453c4421ceaSFande Kong /*@C
4454c4421ceaSFande Kong    SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4455c4421ceaSFande Kong     end of the nonlinear solver to display the conver reason of the nonlinear solver.
4456c4421ceaSFande Kong 
4457c3339decSBarry Smith    Logically Collective
4458c4421ceaSFande Kong 
4459c4421ceaSFande Kong    Input Parameters:
4460f6dfbefdSBarry Smith +  snes - the `SNES` context
4461c4421ceaSFande Kong .  f - the snes converged reason view function
4462c4421ceaSFande Kong .  vctx - [optional] user-defined context for private data for the
4463dc4c0fb0SBarry Smith           snes converged reason view routine (use `NULL` if no context is desired)
4464dc4c0fb0SBarry Smith -  reasonviewdestroy - [optional] routine that frees reasonview context (may be `NULL`)
4465c4421ceaSFande Kong 
4466c4421ceaSFande Kong    Options Database Keys:
4467f6dfbefdSBarry Smith +    -snes_converged_reason        - sets a default `SNESConvergedReasonView()`
4468c4421ceaSFande Kong -    -snes_converged_reason_view_cancel - cancels all converged reason viewers that have
4469c4421ceaSFande Kong                             been hardwired into a code by
4470f6dfbefdSBarry Smith                             calls to `SNESConvergedReasonViewSet()`, but
4471c4421ceaSFande Kong                             does not cancel those set via
4472c4421ceaSFande Kong                             the options database.
4473c4421ceaSFande Kong 
4474dc4c0fb0SBarry Smith    Level: intermediate
4475dc4c0fb0SBarry Smith 
4476f6dfbefdSBarry Smith    Note:
4477c4421ceaSFande Kong    Several different converged reason view routines may be set by calling
4478f6dfbefdSBarry Smith    `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4479c4421ceaSFande Kong    order in which they were set.
4480c4421ceaSFande Kong 
4481dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4482c4421ceaSFande Kong @*/
4483d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES, void *), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **))
4484d71ae5a4SJacob Faibussowitsch {
4485c4421ceaSFande Kong   PetscInt  i;
4486c4421ceaSFande Kong   PetscBool identical;
4487c4421ceaSFande Kong 
4488c4421ceaSFande Kong   PetscFunctionBegin;
4489c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4490c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
44919566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
44923ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4493c4421ceaSFande Kong   }
44945f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4495c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4496c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4497c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
44983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4499c4421ceaSFande Kong }
4500c4421ceaSFande Kong 
450191f3e32bSBarry Smith /*@
4502f6dfbefdSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed.
4503c4421ceaSFande Kong                                        All the user-provided convergedReasonView routines will be involved as well, if they exist.
45042a359c20SBarry Smith 
4505c3339decSBarry Smith   Collective
45062a359c20SBarry Smith 
45072a359c20SBarry Smith   Input Parameters:
4508f6dfbefdSBarry Smith . snes   - the `SNES` object
45092a359c20SBarry Smith 
4510f6dfbefdSBarry Smith   Level: advanced
45112a359c20SBarry Smith 
4512dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4513f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
45142a359c20SBarry Smith @*/
4515d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4516d71ae5a4SJacob Faibussowitsch {
45172a359c20SBarry Smith   PetscViewer       viewer;
45182a359c20SBarry Smith   PetscBool         flg;
45192a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
45202a359c20SBarry Smith   PetscViewerFormat format;
4521c4421ceaSFande Kong   PetscInt          i;
45222a359c20SBarry Smith 
45232a359c20SBarry Smith   PetscFunctionBegin;
45243ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
45252a359c20SBarry Smith   incall = PETSC_TRUE;
4526c4421ceaSFande Kong 
4527c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
452848a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4529c4421ceaSFande Kong 
4530c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
45319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
45322a359c20SBarry Smith   if (flg) {
45339566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
45349566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
45359566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
45369566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
45372a359c20SBarry Smith   }
45382a359c20SBarry Smith   incall = PETSC_FALSE;
45393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45402a359c20SBarry Smith }
45412a359c20SBarry Smith 
4542487a658cSBarry Smith /*@
4543f69a0ea3SMatthew Knepley    SNESSolve - Solves a nonlinear system F(x) = b.
4544f6dfbefdSBarry Smith    Call `SNESSolve()` after calling `SNESCreate()` and optional routines of the form `SNESSetXXX()`.
45459b94acceSBarry Smith 
4546c3339decSBarry Smith    Collective
4547c7afd0dbSLois Curfman McInnes 
4548b2002411SLois Curfman McInnes    Input Parameters:
4549f6dfbefdSBarry Smith +  snes - the `SNES` context
4550dc4c0fb0SBarry Smith .  b - the constant part of the equation F(x) = b, or `NULL` to use zero.
455185385478SLisandro Dalcin -  x - the solution vector.
45529b94acceSBarry Smith 
4553dc4c0fb0SBarry Smith    Level: beginner
4554dc4c0fb0SBarry Smith 
4555f6dfbefdSBarry Smith    Note:
45568ddd3da0SLois Curfman McInnes    The user should initialize the vector,x, with the initial guess
4557f6dfbefdSBarry Smith    for the nonlinear solve prior to calling `SNESSolve()`.  In particular,
45588ddd3da0SLois Curfman McInnes    to employ an initial guess of zero, the user should explicitly set
4559f6dfbefdSBarry Smith    this vector to zero by calling `VecSet()`.
45608ddd3da0SLois Curfman McInnes 
4561dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4562db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4563db781477SPatrick Sanan           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
45649b94acceSBarry Smith @*/
4565d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4566d71ae5a4SJacob Faibussowitsch {
4567ace3abfcSBarry Smith   PetscBool flg;
4568efd51863SBarry Smith   PetscInt  grid;
45690298fd71SBarry Smith   Vec       xcreated = NULL;
4570caa4e7f2SJed Brown   DM        dm;
4571052efed2SBarry Smith 
45723a40ed3dSBarry Smith   PetscFunctionBegin;
45730700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4574a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4575a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
45760700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
457785385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
457885385478SLisandro Dalcin 
457934b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
458006fc46c8SMatthew G. Knepley   {
458106fc46c8SMatthew G. Knepley     PetscViewer       viewer;
458206fc46c8SMatthew G. Knepley     PetscViewerFormat format;
45837c88af5aSMatthew G. Knepley     PetscInt          num;
458406fc46c8SMatthew G. Knepley     PetscBool         flg;
458506fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
458606fc46c8SMatthew G. Knepley 
458706fc46c8SMatthew G. Knepley     if (!incall) {
458834b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
45899566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
459006fc46c8SMatthew G. Knepley       if (flg) {
459106fc46c8SMatthew G. Knepley         PetscConvEst conv;
459246079b62SMatthew G. Knepley         DM           dm;
459346079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
459446079b62SMatthew G. Knepley         PetscInt     Nf;
459506fc46c8SMatthew G. Knepley 
459606fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
45979566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
45989566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
45999566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
46009566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
46019566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
46029566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
46039566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
46049566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
46059566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
46069566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
46079566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
46089566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
46099566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
46109566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
461106fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
461206fc46c8SMatthew G. Knepley       }
461334b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4614b2588ea6SMatthew G. Knepley       num = 1;
46159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
461634b4d3a8SMatthew G. Knepley       if (flg) {
461734b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
461834b4d3a8SMatthew G. Knepley 
461934b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
46209566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46219566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46229566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46239566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46249566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46259566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
46269566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
462734b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
462834b4d3a8SMatthew G. Knepley       }
46297c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
46307c88af5aSMatthew G. Knepley       num = 0;
46319566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
46327c88af5aSMatthew G. Knepley       if (num) {
46337c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
46347c88af5aSMatthew G. Knepley 
46357c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
46369566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46379566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46389566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46399566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46409566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46419566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
46429566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
46437c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
46447c88af5aSMatthew G. Knepley       }
464506fc46c8SMatthew G. Knepley     }
464606fc46c8SMatthew G. Knepley   }
4647ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4648caa4e7f2SJed Brown   if (!x) {
46499566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
46509566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4651a69afd8bSBarry Smith     x = xcreated;
4652a69afd8bSBarry Smith   }
46539566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4654f05ece33SBarry Smith 
46559566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4656efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
465785385478SLisandro Dalcin     /* set solution vector */
46589566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
46599566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
466085385478SLisandro Dalcin     snes->vec_sol = x;
46619566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4662caa4e7f2SJed Brown 
4663caa4e7f2SJed Brown     /* set affine vector if provided */
46649566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
46659566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
466685385478SLisandro Dalcin     snes->vec_rhs = b;
466785385478SLisandro Dalcin 
46685f80ce2aSJacob 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");
46695f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
46705f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector");
4671aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
46729566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
46739566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
46743f149594SLisandro Dalcin 
46757eee914bSBarry Smith     if (!grid) {
467625e27a38SBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4677dd568438SSatish Balay     }
4678d25893d9SBarry Smith 
4679abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
46809371c9d4SSatish Balay     if (snes->counters_reset) {
46819371c9d4SSatish Balay       snes->nfuncs      = 0;
46829371c9d4SSatish Balay       snes->linear_its  = 0;
46839371c9d4SSatish Balay       snes->numFailures = 0;
46849371c9d4SSatish Balay     }
4685d5e45103SBarry Smith 
46869566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4687dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
46889566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
46895f80ce2aSJacob Faibussowitsch     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver returned without setting converged reason");
4690422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
46913f149594SLisandro Dalcin 
469237ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
469337ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
469437ec4e1aSPeter Brune 
46959566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
46969566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4697c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
46989566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
46995968eb51SBarry Smith 
47005f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
47019c8e83a9SBarry Smith     if (snes->reason < 0) break;
4702efd51863SBarry Smith     if (grid < snes->gridsequence) {
4703efd51863SBarry Smith       DM  fine;
4704efd51863SBarry Smith       Vec xnew;
4705efd51863SBarry Smith       Mat interp;
4706efd51863SBarry Smith 
47079566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
47085f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
47099566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
47109566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
47119566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
47129566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
47139566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4714efd51863SBarry Smith       x = xnew;
4715efd51863SBarry Smith 
47169566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
47179566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
47189566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
47199566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
47209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4721efd51863SBarry Smith     }
4722efd51863SBarry Smith   }
47239566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
47249566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
47259566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
47269566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
47273f7e2da0SPeter Brune 
47289566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
47299566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
47303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47319b94acceSBarry Smith }
47329b94acceSBarry Smith 
47339b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
47349b94acceSBarry Smith 
473582bf6240SBarry Smith /*@C
47364b0e389bSBarry Smith    SNESSetType - Sets the method for the nonlinear solver.
47379b94acceSBarry Smith 
4738c3339decSBarry Smith    Collective
4739fee21e36SBarry Smith 
4740c7afd0dbSLois Curfman McInnes    Input Parameters:
4741f6dfbefdSBarry Smith +  snes - the `SNES` context
4742454a90a3SBarry Smith -  type - a known method
4743c7afd0dbSLois Curfman McInnes 
4744c7afd0dbSLois Curfman McInnes    Options Database Key:
4745454a90a3SBarry Smith .  -snes_type <type> - Sets the method; use -help for a list
474604d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4747ae12b187SLois Curfman McInnes 
4748dc4c0fb0SBarry Smith   Level: intermediate
4749dc4c0fb0SBarry Smith 
47509b94acceSBarry Smith    Notes:
4751e090d566SSatish Balay    See "petsc/include/petscsnes.h" for available methods (for instance)
4752f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4753c7afd0dbSLois Curfman McInnes      (systems of nonlinear equations)
47544a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4755c7afd0dbSLois Curfman McInnes      (systems of nonlinear equations)
47569b94acceSBarry Smith 
4757f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4758f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4759ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4760ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4761f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4762ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4763ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4764ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4765ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4766b0a32e0cSBarry Smith   appropriate method.
476736851e7fSLois Curfman McInnes 
4768f6dfbefdSBarry Smith     Developer Note:
4769f6dfbefdSBarry Smith     `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4770f6dfbefdSBarry Smith     the constructor in that list and calls it to create the specific object.
47718f6c3df8SBarry Smith 
4772dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
47739b94acceSBarry Smith @*/
4774d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4775d71ae5a4SJacob Faibussowitsch {
4776ace3abfcSBarry Smith   PetscBool match;
47775f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
47783a40ed3dSBarry Smith 
47793a40ed3dSBarry Smith   PetscFunctionBegin;
47800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47814482741eSBarry Smith   PetscValidCharPointer(type, 2);
478282bf6240SBarry Smith 
47839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
47843ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
478592ff6ae8SBarry Smith 
47869566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
47875f80ce2aSJacob Faibussowitsch   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
478875396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4789dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
479075396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
47919e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
47929e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
47939e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
47949e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
47959e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
47967fe760d5SStefano Zampini 
47977fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
47989566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
47997fe760d5SStefano Zampini 
480075396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
480175396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4802f5af7f23SKarl Rupp 
48039566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
48049566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
48053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48069b94acceSBarry Smith }
48079b94acceSBarry Smith 
48089b94acceSBarry Smith /*@C
4809f6dfbefdSBarry Smith    SNESGetType - Gets the `SNES` method type and name (as a string).
48109b94acceSBarry Smith 
4811c7afd0dbSLois Curfman McInnes    Not Collective
4812c7afd0dbSLois Curfman McInnes 
48139b94acceSBarry Smith    Input Parameter:
48144b0e389bSBarry Smith .  snes - nonlinear solver context
48159b94acceSBarry Smith 
48169b94acceSBarry Smith    Output Parameter:
4817f6dfbefdSBarry Smith .  type - `SNES` method (a character string)
48189b94acceSBarry Smith 
481936851e7fSLois Curfman McInnes    Level: intermediate
482036851e7fSLois Curfman McInnes 
4821dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
48229b94acceSBarry Smith @*/
4823d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4824d71ae5a4SJacob Faibussowitsch {
48253a40ed3dSBarry Smith   PetscFunctionBegin;
48260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48274482741eSBarry Smith   PetscValidPointer(type, 2);
48287adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
48293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48309b94acceSBarry Smith }
48319b94acceSBarry Smith 
48323cd8a7caSMatthew G. Knepley /*@
4833f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
48343cd8a7caSMatthew G. Knepley 
4835c3339decSBarry Smith   Logically Collective
48363cd8a7caSMatthew G. Knepley 
48373cd8a7caSMatthew G. Knepley   Input Parameters:
4838f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
48393cd8a7caSMatthew G. Knepley - u    - the solution vector
48403cd8a7caSMatthew G. Knepley 
48413cd8a7caSMatthew G. Knepley   Level: beginner
48423cd8a7caSMatthew G. Knepley 
4843dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
48443cd8a7caSMatthew G. Knepley @*/
4845d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4846d71ae5a4SJacob Faibussowitsch {
48473cd8a7caSMatthew G. Knepley   DM dm;
48483cd8a7caSMatthew G. Knepley 
48493cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
48503cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48513cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
48529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
48539566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
48543cd8a7caSMatthew G. Knepley 
48553cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
48563cd8a7caSMatthew G. Knepley 
48579566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
48589566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
48593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48603cd8a7caSMatthew G. Knepley }
48613cd8a7caSMatthew G. Knepley 
486252baeb72SSatish Balay /*@
48639b94acceSBarry Smith    SNESGetSolution - Returns the vector where the approximate solution is
4864f6dfbefdSBarry Smith    stored. This is the fine grid solution when using `SNESSetGridSequence()`.
48659b94acceSBarry Smith 
4866f6dfbefdSBarry Smith    Not Collective, but x is parallel if snes is parallel
4867c7afd0dbSLois Curfman McInnes 
48689b94acceSBarry Smith    Input Parameter:
4869f6dfbefdSBarry Smith .  snes - the `SNES` context
48709b94acceSBarry Smith 
48719b94acceSBarry Smith    Output Parameter:
48729b94acceSBarry Smith .  x - the solution
48739b94acceSBarry Smith 
487470e92668SMatthew Knepley    Level: intermediate
487536851e7fSLois Curfman McInnes 
4876dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
48779b94acceSBarry Smith @*/
4878d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4879d71ae5a4SJacob Faibussowitsch {
48803a40ed3dSBarry Smith   PetscFunctionBegin;
48810700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48824482741eSBarry Smith   PetscValidPointer(x, 2);
488385385478SLisandro Dalcin   *x = snes->vec_sol;
48843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
488570e92668SMatthew Knepley }
488670e92668SMatthew Knepley 
488752baeb72SSatish Balay /*@
48889b94acceSBarry Smith    SNESGetSolutionUpdate - Returns the vector where the solution update is
48899b94acceSBarry Smith    stored.
48909b94acceSBarry Smith 
4891f6dfbefdSBarry Smith    Not Collective, but x is parallel if snes is parallel
4892c7afd0dbSLois Curfman McInnes 
48939b94acceSBarry Smith    Input Parameter:
4894f6dfbefdSBarry Smith .  snes - the `SNES` context
48959b94acceSBarry Smith 
48969b94acceSBarry Smith    Output Parameter:
48979b94acceSBarry Smith .  x - the solution update
48989b94acceSBarry Smith 
489936851e7fSLois Curfman McInnes    Level: advanced
490036851e7fSLois Curfman McInnes 
4901dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
49029b94acceSBarry Smith @*/
4903d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4904d71ae5a4SJacob Faibussowitsch {
49053a40ed3dSBarry Smith   PetscFunctionBegin;
49060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49074482741eSBarry Smith   PetscValidPointer(x, 2);
490885385478SLisandro Dalcin   *x = snes->vec_sol_update;
49093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49109b94acceSBarry Smith }
49119b94acceSBarry Smith 
49129b94acceSBarry Smith /*@C
4913f6dfbefdSBarry Smith    SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
49149b94acceSBarry Smith 
4915f6dfbefdSBarry Smith    Not Collective, but r is parallel if snes is parallel. Collective if r is requested, but has not been created yet.
4916c7afd0dbSLois Curfman McInnes 
49179b94acceSBarry Smith    Input Parameter:
4918f6dfbefdSBarry Smith .  snes - the `SNES` context
49199b94acceSBarry Smith 
4920d8d19677SJose E. Roman    Output Parameters:
4921dc4c0fb0SBarry Smith +  r - the vector that is used to store residuals (or `NULL` if you don't want it)
4922*20f4b53cSBarry Smith .  f - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunction`
4923dc4c0fb0SBarry Smith -  ctx - the function context (or `NULL` if you don't want it)
49249b94acceSBarry Smith 
492536851e7fSLois Curfman McInnes    Level: advanced
492636851e7fSLois Curfman McInnes 
4927f6dfbefdSBarry Smith     Note:
4928dc4c0fb0SBarry Smith    The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
492904edfde5SBarry Smith 
4930dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction`
49319b94acceSBarry Smith @*/
4932d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4933d71ae5a4SJacob Faibussowitsch {
49346cab3a1bSJed Brown   DM dm;
4935a63bb30eSJed Brown 
49363a40ed3dSBarry Smith   PetscFunctionBegin;
49370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4938a63bb30eSJed Brown   if (r) {
4939a63bb30eSJed Brown     if (!snes->vec_func) {
4940a63bb30eSJed Brown       if (snes->vec_rhs) {
49419566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
4942a63bb30eSJed Brown       } else if (snes->vec_sol) {
49439566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
4944a63bb30eSJed Brown       } else if (snes->dm) {
49459566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
4946a63bb30eSJed Brown       }
4947a63bb30eSJed Brown     }
4948a63bb30eSJed Brown     *r = snes->vec_func;
4949a63bb30eSJed Brown   }
49509566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49519566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
49523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49539b94acceSBarry Smith }
49549b94acceSBarry Smith 
4955c79ef259SPeter Brune /*@C
4956f6dfbefdSBarry Smith    SNESGetNGS - Returns the `SNESNGS` function and context set with `SNESSetNGS()`
4957c79ef259SPeter Brune 
4958c79ef259SPeter Brune    Input Parameter:
4959f6dfbefdSBarry Smith .  snes - the `SNES` context
4960c79ef259SPeter Brune 
4961d8d19677SJose E. Roman    Output Parameters:
4962dc4c0fb0SBarry Smith +  f - the function (or `NULL`) see `SNESNGSFunction` for details
4963dc4c0fb0SBarry Smith -  ctx    - the function context (or `NULL`)
4964c79ef259SPeter Brune 
4965c79ef259SPeter Brune    Level: advanced
4966c79ef259SPeter Brune 
4967dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetNGS()`, `SNESGetFunction()`
4968c79ef259SPeter Brune @*/
4969c79ef259SPeter Brune 
4970d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4971d71ae5a4SJacob Faibussowitsch {
49726cab3a1bSJed Brown   DM dm;
49736cab3a1bSJed Brown 
4974646217ecSPeter Brune   PetscFunctionBegin;
4975646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49769566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49779566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
49783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4979646217ecSPeter Brune }
4980646217ecSPeter Brune 
49813c7409f5SSatish Balay /*@C
49823c7409f5SSatish Balay    SNESSetOptionsPrefix - Sets the prefix used for searching for all
4983f6dfbefdSBarry Smith    `SNES` options in the database.
49843c7409f5SSatish Balay 
4985c3339decSBarry Smith    Logically Collective
4986fee21e36SBarry Smith 
4987d8d19677SJose E. Roman    Input Parameters:
4988f6dfbefdSBarry Smith +  snes - the `SNES` context
4989c7afd0dbSLois Curfman McInnes -  prefix - the prefix to prepend to all option names
4990c7afd0dbSLois Curfman McInnes 
4991dc4c0fb0SBarry Smith    Level: advanced
4992dc4c0fb0SBarry Smith 
4993f6dfbefdSBarry Smith    Note:
4994a83b1b31SSatish Balay    A hyphen (-) must NOT be given at the beginning of the prefix name.
4995c7afd0dbSLois Curfman McInnes    The first character of all runtime options is AUTOMATICALLY the hyphen.
4996d850072dSLois Curfman McInnes 
4997dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
49983c7409f5SSatish Balay @*/
4999d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5000d71ae5a4SJacob Faibussowitsch {
50013a40ed3dSBarry Smith   PetscFunctionBegin;
50020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50039566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
50049566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
500535f5d045SPeter Brune   if (snes->linesearch) {
50069566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50079566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
500835f5d045SPeter Brune   }
50099566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
50103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50113c7409f5SSatish Balay }
50123c7409f5SSatish Balay 
50133c7409f5SSatish Balay /*@C
5014f525115eSLois Curfman McInnes    SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5015f6dfbefdSBarry Smith    `SNES` options in the database.
50163c7409f5SSatish Balay 
5017c3339decSBarry Smith    Logically Collective
5018fee21e36SBarry Smith 
5019c7afd0dbSLois Curfman McInnes    Input Parameters:
5020f6dfbefdSBarry Smith +  snes - the `SNES` context
5021c7afd0dbSLois Curfman McInnes -  prefix - the prefix to prepend to all option names
5022c7afd0dbSLois Curfman McInnes 
5023dc4c0fb0SBarry Smith    Level: advanced
5024dc4c0fb0SBarry Smith 
5025f6dfbefdSBarry Smith    Note:
5026a83b1b31SSatish Balay    A hyphen (-) must NOT be given at the beginning of the prefix name.
5027c7afd0dbSLois Curfman McInnes    The first character of all runtime options is AUTOMATICALLY the hyphen.
5028d850072dSLois Curfman McInnes 
5029dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
50303c7409f5SSatish Balay @*/
5031d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5032d71ae5a4SJacob Faibussowitsch {
50333a40ed3dSBarry Smith   PetscFunctionBegin;
50340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50359566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
50369566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
503735f5d045SPeter Brune   if (snes->linesearch) {
50389566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50399566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
504035f5d045SPeter Brune   }
50419566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
50423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50433c7409f5SSatish Balay }
50443c7409f5SSatish Balay 
50459ab63eb5SSatish Balay /*@C
5046f6dfbefdSBarry Smith    SNESGetOptionsPrefix - Gets the prefix used for searching for all
5047f6dfbefdSBarry Smith    `SNES` options in the database.
50483c7409f5SSatish Balay 
5049c7afd0dbSLois Curfman McInnes    Not Collective
5050c7afd0dbSLois Curfman McInnes 
50513c7409f5SSatish Balay    Input Parameter:
5052f6dfbefdSBarry Smith .  snes - the `SNES` context
50533c7409f5SSatish Balay 
50543c7409f5SSatish Balay    Output Parameter:
50553c7409f5SSatish Balay .  prefix - pointer to the prefix string used
50563c7409f5SSatish Balay 
505736851e7fSLois Curfman McInnes    Level: advanced
505836851e7fSLois Curfman McInnes 
5059dc4c0fb0SBarry Smith    Fortran Note:
5060dc4c0fb0SBarry Smith     The user should pass in a string 'prefix' of
5061dc4c0fb0SBarry Smith    sufficient length to hold the prefix.
5062dc4c0fb0SBarry Smith 
5063dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
50643c7409f5SSatish Balay @*/
5065d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5066d71ae5a4SJacob Faibussowitsch {
50673a40ed3dSBarry Smith   PetscFunctionBegin;
50680700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50699566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
50703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50713c7409f5SSatish Balay }
50723c7409f5SSatish Balay 
50733cea93caSBarry Smith /*@C
50741c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
50751c84c290SBarry Smith 
5076*20f4b53cSBarry Smith    Not Collective
50771c84c290SBarry Smith 
50781c84c290SBarry Smith    Input Parameters:
5079*20f4b53cSBarry Smith +  sname - name of a new user-defined solver
5080*20f4b53cSBarry Smith -  function - routine to create method context
50811c84c290SBarry Smith 
5082dc4c0fb0SBarry Smith    Level: advanced
5083dc4c0fb0SBarry Smith 
5084f6dfbefdSBarry Smith    Note:
5085f6dfbefdSBarry Smith    `SNESRegister()` may be called multiple times to add several user-defined solvers.
50861c84c290SBarry Smith 
50871c84c290SBarry Smith    Sample usage:
50881c84c290SBarry Smith .vb
5089bdf89e91SBarry Smith    SNESRegister("my_solver",MySolverCreate);
50901c84c290SBarry Smith .ve
50911c84c290SBarry Smith 
50921c84c290SBarry Smith    Then, your solver can be chosen with the procedural interface via
50931c84c290SBarry Smith $     SNESSetType(snes,"my_solver")
50941c84c290SBarry Smith    or at runtime via the option
50951c84c290SBarry Smith $     -snes_type my_solver
50961c84c290SBarry Smith 
5097dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
50983cea93caSBarry Smith @*/
5099d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5100d71ae5a4SJacob Faibussowitsch {
5101b2002411SLois Curfman McInnes   PetscFunctionBegin;
51029566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
51039566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
51043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5105b2002411SLois Curfman McInnes }
5106da9b6338SBarry Smith 
5107d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5108d71ae5a4SJacob Faibussowitsch {
510977431f27SBarry Smith   PetscInt    N, i, j;
5110da9b6338SBarry Smith   Vec         u, uh, fh;
5111da9b6338SBarry Smith   PetscScalar value;
5112da9b6338SBarry Smith   PetscReal   norm;
5113da9b6338SBarry Smith 
5114da9b6338SBarry Smith   PetscFunctionBegin;
51159566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
51169566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
51179566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5118da9b6338SBarry Smith 
5119da9b6338SBarry Smith   /* currently only works for sequential */
51209566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
51219566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5122da9b6338SBarry Smith   for (i = 0; i < N; i++) {
51239566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
512463a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5125da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
51268b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
51279566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
51289566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
51299566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
513063a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5131da9b6338SBarry Smith       value = -value;
51329566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5133da9b6338SBarry Smith     }
5134da9b6338SBarry Smith   }
51359566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
51369566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
51373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5138da9b6338SBarry Smith }
513971f87433Sdalcinl 
514071f87433Sdalcinl /*@
5141f6dfbefdSBarry Smith    SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
514271f87433Sdalcinl    computing relative tolerance for linear solvers within an inexact
514371f87433Sdalcinl    Newton method.
514471f87433Sdalcinl 
5145c3339decSBarry Smith    Logically Collective
514671f87433Sdalcinl 
514771f87433Sdalcinl    Input Parameters:
5148f6dfbefdSBarry Smith +  snes - `SNES` context
5149f6dfbefdSBarry Smith -  flag - `PETSC_TRUE` or `PETSC_FALSE`
515071f87433Sdalcinl 
5151f6dfbefdSBarry Smith     Options Database Keys:
515264ba62caSBarry Smith +  -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
515364ba62caSBarry Smith .  -snes_ksp_ew_version ver - version of  Eisenstat-Walker method
515464ba62caSBarry Smith .  -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
515564ba62caSBarry Smith .  -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
515664ba62caSBarry Smith .  -snes_ksp_ew_gamma <gamma> - Sets gamma
515764ba62caSBarry Smith .  -snes_ksp_ew_alpha <alpha> - Sets alpha
515864ba62caSBarry Smith .  -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
515964ba62caSBarry Smith -  -snes_ksp_ew_threshold <threshold> - Sets threshold
516064ba62caSBarry Smith 
5161dc4c0fb0SBarry Smith    Level: advanced
5162dc4c0fb0SBarry Smith 
5163f6dfbefdSBarry Smith    Note:
5164f6dfbefdSBarry Smith    The default is to use a constant relative tolerance for
516571f87433Sdalcinl    the inner linear solvers.  Alternatively, one can use the
516671f87433Sdalcinl    Eisenstat-Walker method, where the relative convergence tolerance
516771f87433Sdalcinl    is reset at each Newton iteration according progress of the nonlinear
516871f87433Sdalcinl    solver.
516971f87433Sdalcinl 
517071f87433Sdalcinl    Reference:
5171f6dfbefdSBarry Smith .  - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996.
517271f87433Sdalcinl 
5173dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
517471f87433Sdalcinl @*/
5175d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5176d71ae5a4SJacob Faibussowitsch {
517771f87433Sdalcinl   PetscFunctionBegin;
51780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5179acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
518071f87433Sdalcinl   snes->ksp_ewconv = flag;
51813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
518271f87433Sdalcinl }
518371f87433Sdalcinl 
518471f87433Sdalcinl /*@
5185f6dfbefdSBarry Smith    SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
518671f87433Sdalcinl    for computing relative tolerance for linear solvers within an
518771f87433Sdalcinl    inexact Newton method.
518871f87433Sdalcinl 
518971f87433Sdalcinl    Not Collective
519071f87433Sdalcinl 
519171f87433Sdalcinl    Input Parameter:
5192f6dfbefdSBarry Smith .  snes - `SNES` context
519371f87433Sdalcinl 
519471f87433Sdalcinl    Output Parameter:
5195f6dfbefdSBarry Smith .  flag - `PETSC_TRUE` or `PETSC_FALSE`
519671f87433Sdalcinl 
519771f87433Sdalcinl    Level: advanced
519871f87433Sdalcinl 
5199dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
520071f87433Sdalcinl @*/
5201d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5202d71ae5a4SJacob Faibussowitsch {
520371f87433Sdalcinl   PetscFunctionBegin;
52040700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5205534a8f05SLisandro Dalcin   PetscValidBoolPointer(flag, 2);
520671f87433Sdalcinl   *flag = snes->ksp_ewconv;
52073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
520871f87433Sdalcinl }
520971f87433Sdalcinl 
521071f87433Sdalcinl /*@
5211fa9f3622SBarry Smith    SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
521271f87433Sdalcinl    convergence criteria for the linear solvers within an inexact
521371f87433Sdalcinl    Newton method.
521471f87433Sdalcinl 
5215c3339decSBarry Smith    Logically Collective
521671f87433Sdalcinl 
521771f87433Sdalcinl    Input Parameters:
5218f6dfbefdSBarry Smith +    snes - `SNES` context
52190f0abf79SStefano Zampini .    version - version 1, 2 (default is 2), 3 or 4
522071f87433Sdalcinl .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
522171f87433Sdalcinl .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
522271f87433Sdalcinl .    gamma - multiplicative factor for version 2 rtol computation
522371f87433Sdalcinl              (0 <= gamma2 <= 1)
522471f87433Sdalcinl .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
522571f87433Sdalcinl .    alpha2 - power for safeguard
522671f87433Sdalcinl -    threshold - threshold for imposing safeguard (0 < threshold < 1)
522771f87433Sdalcinl 
5228dc4c0fb0SBarry Smith    Level: advanced
5229dc4c0fb0SBarry Smith 
5230f6dfbefdSBarry Smith    Notes:
523171f87433Sdalcinl    Version 3 was contributed by Luis Chacon, June 2006.
523271f87433Sdalcinl 
5233f6dfbefdSBarry Smith    Use `PETSC_DEFAULT` to retain the default for any of the parameters.
523471f87433Sdalcinl 
5235dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
523671f87433Sdalcinl @*/
5237d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5238d71ae5a4SJacob Faibussowitsch {
5239fa9f3622SBarry Smith   SNESKSPEW *kctx;
52405fd66863SKarl Rupp 
524171f87433Sdalcinl   PetscFunctionBegin;
52420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5243fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52445f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5245c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5246c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5247c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5248c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5249c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5250c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5251c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
525271f87433Sdalcinl 
525371f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
525413bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
525513bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
525613bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
525713bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
525813bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
525913bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
526071f87433Sdalcinl 
52610f0abf79SStefano 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);
52620b121fc5SBarry 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);
52630b121fc5SBarry 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);
52640b121fc5SBarry 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);
52650b121fc5SBarry 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);
52660b121fc5SBarry 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);
52673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
526871f87433Sdalcinl }
526971f87433Sdalcinl 
527071f87433Sdalcinl /*@
5271fa9f3622SBarry Smith    SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
527271f87433Sdalcinl    convergence criteria for the linear solvers within an inexact
527371f87433Sdalcinl    Newton method.
527471f87433Sdalcinl 
527571f87433Sdalcinl    Not Collective
527671f87433Sdalcinl 
527797bb3fdcSJose E. Roman    Input Parameter:
5278f6dfbefdSBarry Smith .    snes - `SNES` context
527971f87433Sdalcinl 
528071f87433Sdalcinl    Output Parameters:
52810f0abf79SStefano Zampini +    version - version 1, 2 (default is 2), 3 or 4
528271f87433Sdalcinl .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
528371f87433Sdalcinl .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
5284bf388a1fSBarry Smith .    gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
528571f87433Sdalcinl .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
528671f87433Sdalcinl .    alpha2 - power for safeguard
528771f87433Sdalcinl -    threshold - threshold for imposing safeguard (0 < threshold < 1)
528871f87433Sdalcinl 
528971f87433Sdalcinl    Level: advanced
529071f87433Sdalcinl 
5291dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
529271f87433Sdalcinl @*/
5293d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5294d71ae5a4SJacob Faibussowitsch {
5295fa9f3622SBarry Smith   SNESKSPEW *kctx;
52965fd66863SKarl Rupp 
529771f87433Sdalcinl   PetscFunctionBegin;
52980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5299fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53005f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
530171f87433Sdalcinl   if (version) *version = kctx->version;
530271f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
530371f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
530471f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
530571f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
530671f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
530771f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
53083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
530971f87433Sdalcinl }
531071f87433Sdalcinl 
5311d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5312d71ae5a4SJacob Faibussowitsch {
5313fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
531471f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
531571f87433Sdalcinl 
531671f87433Sdalcinl   PetscFunctionBegin;
53173ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
531830058271SDmitry Karpeev   if (!snes->iter) {
531930058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
53209566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
53210f0abf79SStefano Zampini   } else {
53220fdf79fbSJacob Faibussowitsch     PetscCheck(kctx->version >= 1 && kctx->version <= 4, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only versions 1-4 are supported: %" PetscInt_FMT, kctx->version);
532371f87433Sdalcinl     if (kctx->version == 1) {
53240f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
532585ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
532671f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
532771f87433Sdalcinl     } else if (kctx->version == 2) {
532885ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
532985ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
533071f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
533171f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
533285ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
533371f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
533485ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
533571f87433Sdalcinl       stol = PetscMax(rtol, stol);
533671f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
533771f87433Sdalcinl       /* safeguard: avoid oversolving */
533830058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
533971f87433Sdalcinl       stol = PetscMax(rtol, stol);
534071f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
53410fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
53420fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
53430f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
53440f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
53450f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
53460f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
53470f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
53480f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
53490f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
53500f0abf79SStefano Zampini 
53519371c9d4SSatish 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) {
53520f0abf79SStefano Zampini         rtol = kctx->v4_m4 * kctx->rtol_last;
53530f0abf79SStefano 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);
53540f0abf79SStefano Zampini       } else {
53550f0abf79SStefano 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);
535671f87433Sdalcinl       }
53570f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
53580f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
53590f0abf79SStefano Zampini       kctx->rk_last     = rk;
53600fdf79fbSJacob Faibussowitsch     }
53610f0abf79SStefano Zampini   }
53620f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
536371f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
53649566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
536563a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
53663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536771f87433Sdalcinl }
536871f87433Sdalcinl 
5369d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5370d71ae5a4SJacob Faibussowitsch {
5371fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
537271f87433Sdalcinl   PCSide     pcside;
537371f87433Sdalcinl   Vec        lres;
537471f87433Sdalcinl 
537571f87433Sdalcinl   PetscFunctionBegin;
53763ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
53779566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
537871dbe336SPeter Brune   kctx->norm_last = snes->norm;
53790f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
53804f00ce20SMatthew G. Knepley     PC        pc;
53810f0abf79SStefano Zampini     PetscBool getRes;
53824f00ce20SMatthew G. Knepley 
53839566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
53840f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
53850f0abf79SStefano Zampini     if (!getRes) {
53860f0abf79SStefano Zampini       KSPNormType normtype;
53870f0abf79SStefano Zampini 
53880f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
53890f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
53900f0abf79SStefano Zampini     }
53919566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
53920f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
53939566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
539471f87433Sdalcinl     } else {
539571f87433Sdalcinl       /* KSP residual is preconditioned residual */
539671f87433Sdalcinl       /* compute true linear residual norm */
53970f0abf79SStefano Zampini       Mat J;
53980f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
53999566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
54000f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
54019566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
54029566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
54039566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
540471f87433Sdalcinl     }
540571f87433Sdalcinl   }
54063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
540771f87433Sdalcinl }
540871f87433Sdalcinl 
5409d4211eb9SBarry Smith /*@
5410f6dfbefdSBarry Smith    SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5411d4211eb9SBarry Smith 
5412f6dfbefdSBarry Smith    Not Collective, but if snes is parallel, then ksp is parallel
5413d4211eb9SBarry Smith 
5414d4211eb9SBarry Smith    Input Parameter:
5415f6dfbefdSBarry Smith .  snes - the `SNES` context
5416d4211eb9SBarry Smith 
5417d4211eb9SBarry Smith    Output Parameter:
5418f6dfbefdSBarry Smith .  ksp - the `KSP` context
5419d4211eb9SBarry Smith 
5420dc4c0fb0SBarry Smith    Level: beginner
5421dc4c0fb0SBarry Smith 
5422d4211eb9SBarry Smith    Notes:
5423f6dfbefdSBarry Smith    The user can then directly manipulate the `KSP` context to set various
5424d4211eb9SBarry Smith    options, etc.  Likewise, the user can then extract and manipulate the
5425f6dfbefdSBarry Smith    `PC` contexts as well.
5426f6dfbefdSBarry Smith 
5427f6dfbefdSBarry Smith    Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5428d4211eb9SBarry Smith 
5429dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5430d4211eb9SBarry Smith @*/
5431d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5432d71ae5a4SJacob Faibussowitsch {
543371f87433Sdalcinl   PetscFunctionBegin;
5434d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5435d4211eb9SBarry Smith   PetscValidPointer(ksp, 2);
5436d4211eb9SBarry Smith 
5437d4211eb9SBarry Smith   if (!snes->ksp) {
54389566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
54399566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5440d4211eb9SBarry Smith 
54419566063dSJacob Faibussowitsch     PetscCall(KSPSetPreSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_SNESEW, snes));
54429566063dSJacob Faibussowitsch     PetscCall(KSPSetPostSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_SNESEW, snes));
5443a5c2985bSBarry Smith 
54449566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
54459566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5446d4211eb9SBarry Smith   }
5447d4211eb9SBarry Smith   *ksp = snes->ksp;
54483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
544971f87433Sdalcinl }
54506c699258SBarry Smith 
5451af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
54526c699258SBarry Smith /*@
5453f6dfbefdSBarry Smith    SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
54546c699258SBarry Smith 
5455c3339decSBarry Smith    Logically Collective
54566c699258SBarry Smith 
54576c699258SBarry Smith    Input Parameters:
54582a808120SBarry Smith +  snes - the nonlinear solver context
5459dc4c0fb0SBarry Smith -  dm - the dm, cannot be `NULL`
5460dc4c0fb0SBarry Smith 
5461dc4c0fb0SBarry Smith    Level: intermediate
54626c699258SBarry Smith 
5463f6dfbefdSBarry Smith    Note:
5464f6dfbefdSBarry Smith    A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5465f6dfbefdSBarry Smith    even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5466e03a659cSJed Brown    problems using the same function space.
5467e03a659cSJed Brown 
5468dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `DM`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
54696c699258SBarry Smith @*/
5470d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5471d71ae5a4SJacob Faibussowitsch {
5472345fed2cSBarry Smith   KSP    ksp;
5473942e3340SBarry Smith   DMSNES sdm;
54746c699258SBarry Smith 
54756c699258SBarry Smith   PetscFunctionBegin;
54760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54772a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
54789566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5479942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
548051f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
54819566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
54829566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5483f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
54846cab3a1bSJed Brown     }
54859566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
54869566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
54876cab3a1bSJed Brown   }
54886c699258SBarry Smith   snes->dm     = dm;
5489116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5490f5af7f23SKarl Rupp 
54919566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
54929566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
54939566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5494efd4aadfSBarry Smith   if (snes->npc) {
54959566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
54969566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
54972c155ee1SBarry Smith   }
54983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54996c699258SBarry Smith }
55006c699258SBarry Smith 
55016c699258SBarry Smith /*@
5502f6dfbefdSBarry Smith    SNESGetDM - Gets the `DM` that may be used by some preconditioners
55036c699258SBarry Smith 
5504f6dfbefdSBarry Smith    Not Collective but dm obtained is parallel on snes
55056c699258SBarry Smith 
55066c699258SBarry Smith    Input Parameter:
55076c699258SBarry Smith . snes - the preconditioner context
55086c699258SBarry Smith 
55096c699258SBarry Smith    Output Parameter:
55106c699258SBarry Smith .  dm - the dm
55116c699258SBarry Smith 
55126c699258SBarry Smith    Level: intermediate
55136c699258SBarry Smith 
5514dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `DM`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
55156c699258SBarry Smith @*/
5516d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5517d71ae5a4SJacob Faibussowitsch {
55186c699258SBarry Smith   PetscFunctionBegin;
55190700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55206cab3a1bSJed Brown   if (!snes->dm) {
55219566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5522116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
55236cab3a1bSJed Brown   }
55246c699258SBarry Smith   *dm = snes->dm;
55253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55266c699258SBarry Smith }
55270807856dSBarry Smith 
552831823bd8SMatthew G Knepley /*@
5529be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
553031823bd8SMatthew G Knepley 
5531c3339decSBarry Smith   Collective
553231823bd8SMatthew G Knepley 
553331823bd8SMatthew G Knepley   Input Parameters:
5534f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5535f6dfbefdSBarry Smith - npc   - the preconditioner object
553631823bd8SMatthew G Knepley 
5537dc4c0fb0SBarry Smith   Level: developer
5538dc4c0fb0SBarry Smith 
553931823bd8SMatthew G Knepley   Notes:
5540f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
554131823bd8SMatthew G Knepley   to configure it using the API).
554231823bd8SMatthew G Knepley 
5543f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5544f6dfbefdSBarry Smith 
5545dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
554631823bd8SMatthew G Knepley @*/
5547d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5548d71ae5a4SJacob Faibussowitsch {
554931823bd8SMatthew G Knepley   PetscFunctionBegin;
555031823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5551f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5552f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5553f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
55549566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5555f6dfbefdSBarry Smith   snes->npc = npc;
55563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
555731823bd8SMatthew G Knepley }
555831823bd8SMatthew G Knepley 
555931823bd8SMatthew G Knepley /*@
5560f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
556131823bd8SMatthew G Knepley 
5562f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
556331823bd8SMatthew G Knepley 
556431823bd8SMatthew G Knepley   Input Parameter:
5565f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
556631823bd8SMatthew G Knepley 
556731823bd8SMatthew G Knepley   Output Parameter:
5568f6dfbefdSBarry Smith . npc - preconditioner context
556931823bd8SMatthew G Knepley 
5570f6dfbefdSBarry Smith   Options Database Key:
5571f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5572b5badacbSBarry Smith 
5573dc4c0fb0SBarry Smith   Level: developer
5574dc4c0fb0SBarry Smith 
557595452b02SPatrick Sanan   Notes:
5576f6dfbefdSBarry Smith     If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5577be95d8f1SBarry Smith 
5578f6dfbefdSBarry Smith     The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5579f6dfbefdSBarry Smith     `SNES`
5580951fe5abSBarry Smith 
5581dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
558231823bd8SMatthew G Knepley @*/
5583d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5584d71ae5a4SJacob Faibussowitsch {
5585a64e098fSPeter Brune   const char *optionsprefix;
558631823bd8SMatthew G Knepley 
558731823bd8SMatthew G Knepley   PetscFunctionBegin;
558831823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
558931823bd8SMatthew G Knepley   PetscValidPointer(pc, 2);
5590efd4aadfSBarry Smith   if (!snes->npc) {
55919566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
55929566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
55939566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
55949566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
55959566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
55969566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
559731823bd8SMatthew G Knepley   }
5598efd4aadfSBarry Smith   *pc = snes->npc;
55993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
560031823bd8SMatthew G Knepley }
560131823bd8SMatthew G Knepley 
56023ad1a0b9SPatrick Farrell /*@
56033ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
56043ad1a0b9SPatrick Farrell 
56053ad1a0b9SPatrick Farrell   Not Collective
56063ad1a0b9SPatrick Farrell 
56073ad1a0b9SPatrick Farrell   Input Parameter:
5608f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56093ad1a0b9SPatrick Farrell 
56103ad1a0b9SPatrick Farrell   Output Parameter:
5611f6dfbefdSBarry Smith . has_npc - whether the `SNES` has an NPC or not
56123ad1a0b9SPatrick Farrell 
56133ad1a0b9SPatrick Farrell   Level: developer
56143ad1a0b9SPatrick Farrell 
5615dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetNPC()`, `SNESGetNPC()`
56163ad1a0b9SPatrick Farrell @*/
5617d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5618d71ae5a4SJacob Faibussowitsch {
56193ad1a0b9SPatrick Farrell   PetscFunctionBegin;
56203ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5621efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
56223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56233ad1a0b9SPatrick Farrell }
56243ad1a0b9SPatrick Farrell 
5625c40d0f55SPeter Brune /*@
5626be95d8f1SBarry Smith     SNESSetNPCSide - Sets the preconditioning side.
5627c40d0f55SPeter Brune 
5628c3339decSBarry Smith     Logically Collective
5629c40d0f55SPeter Brune 
5630c40d0f55SPeter Brune     Input Parameter:
5631f6dfbefdSBarry Smith .   snes - iterative context obtained from `SNESCreate()`
5632c40d0f55SPeter Brune 
5633c40d0f55SPeter Brune     Output Parameter:
5634c40d0f55SPeter Brune .   side - the preconditioning side, where side is one of
5635c40d0f55SPeter Brune .vb
56362d547940SBarry Smith       PC_LEFT - left preconditioning
56372d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5638c40d0f55SPeter Brune .ve
5639c40d0f55SPeter Brune 
5640f6dfbefdSBarry Smith     Options Database Key:
564167b8a455SSatish Balay .   -snes_npc_side <right,left> - nonlinear preconditioner side
5642c40d0f55SPeter Brune 
5643dc4c0fb0SBarry Smith     Level: intermediate
5644dc4c0fb0SBarry Smith 
5645f6dfbefdSBarry Smith     Note:
5646f6dfbefdSBarry Smith     `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
56472d547940SBarry Smith 
5648dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`
5649c40d0f55SPeter Brune @*/
5650d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5651d71ae5a4SJacob Faibussowitsch {
5652c40d0f55SPeter Brune   PetscFunctionBegin;
5653c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5654c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5655b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
565654c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5657efd4aadfSBarry Smith   snes->npcside = side;
56583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5659c40d0f55SPeter Brune }
5660c40d0f55SPeter Brune 
5661c40d0f55SPeter Brune /*@
5662be95d8f1SBarry Smith     SNESGetNPCSide - Gets the preconditioning side.
5663c40d0f55SPeter Brune 
5664c40d0f55SPeter Brune     Not Collective
5665c40d0f55SPeter Brune 
5666c40d0f55SPeter Brune     Input Parameter:
5667f6dfbefdSBarry Smith .   snes - iterative context obtained from `SNESCreate()`
5668c40d0f55SPeter Brune 
5669c40d0f55SPeter Brune     Output Parameter:
5670c40d0f55SPeter Brune .   side - the preconditioning side, where side is one of
5671c40d0f55SPeter Brune .vb
5672f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5673f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5674c40d0f55SPeter Brune .ve
5675c40d0f55SPeter Brune 
5676c40d0f55SPeter Brune     Level: intermediate
5677c40d0f55SPeter Brune 
5678dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`
5679c40d0f55SPeter Brune @*/
5680d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5681d71ae5a4SJacob Faibussowitsch {
5682c40d0f55SPeter Brune   PetscFunctionBegin;
5683c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5684c40d0f55SPeter Brune   PetscValidPointer(side, 2);
5685efd4aadfSBarry Smith   *side = snes->npcside;
56863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5687c40d0f55SPeter Brune }
5688c40d0f55SPeter Brune 
56899e764e56SPeter Brune /*@
5690f6dfbefdSBarry Smith   SNESSetLineSearch - Sets the linesearch on the `SNES` instance.
56919e764e56SPeter Brune 
5692c3339decSBarry Smith   Collective
56939e764e56SPeter Brune 
56949e764e56SPeter Brune   Input Parameters:
5695f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
56969e764e56SPeter Brune - linesearch   - the linesearch object
56979e764e56SPeter Brune 
5698dc4c0fb0SBarry Smith   Level: developer
5699dc4c0fb0SBarry Smith 
5700f6dfbefdSBarry Smith   Note:
5701f6dfbefdSBarry Smith   Use `SNESGetLineSearch()` to retrieve the preconditioner context (for example,
57029e764e56SPeter Brune   to configure it using the API).
57039e764e56SPeter Brune 
5704dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetLineSearch()`
57059e764e56SPeter Brune @*/
5706d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5707d71ae5a4SJacob Faibussowitsch {
57089e764e56SPeter Brune   PetscFunctionBegin;
57099e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5710f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
57119e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
57129566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
57139566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5714f5af7f23SKarl Rupp 
57159e764e56SPeter Brune   snes->linesearch = linesearch;
5716f5af7f23SKarl Rupp 
57173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57189e764e56SPeter Brune }
57199e764e56SPeter Brune 
5720a34ceb2aSJed Brown /*@
5721dc4c0fb0SBarry Smith   SNESGetLineSearch - Returns the line search context set with `SNESSetLineSearch()`
5722f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
57239e764e56SPeter Brune 
57249e764e56SPeter Brune   Not Collective
57259e764e56SPeter Brune 
57269e764e56SPeter Brune   Input Parameter:
5727f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57289e764e56SPeter Brune 
57299e764e56SPeter Brune   Output Parameter:
57309e764e56SPeter Brune . linesearch - linesearch context
57319e764e56SPeter Brune 
5732162e0bf5SPeter Brune   Level: beginner
57339e764e56SPeter Brune 
5734dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
57359e764e56SPeter Brune @*/
5736d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5737d71ae5a4SJacob Faibussowitsch {
57389e764e56SPeter Brune   const char *optionsprefix;
57399e764e56SPeter Brune 
57409e764e56SPeter Brune   PetscFunctionBegin;
57419e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57429e764e56SPeter Brune   PetscValidPointer(linesearch, 2);
57439e764e56SPeter Brune   if (!snes->linesearch) {
57449566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57459566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
57469566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
57479566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
57489566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
57499e764e56SPeter Brune   }
57509e764e56SPeter Brune   *linesearch = snes->linesearch;
57513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57529e764e56SPeter Brune }
5753