xref: /petsc/src/snes/interface/snes.c (revision aaa8cc7d2a5c3913edcbb923e20f154fe9c4aa65)
1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h"  I*/
207475bc1SBarry Smith #include <petscdmshell.h>
3d96771aaSLisandro Dalcin #include <petscdraw.h>
4a01aa210SMatthew G. Knepley #include <petscds.h>
534b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h>
606fc46c8SMatthew G. Knepley #include <petscconvest.h>
79b94acceSBarry Smith 
8ace3abfcSBarry Smith PetscBool         SNESRegisterAllCalled = PETSC_FALSE;
90298fd71SBarry Smith PetscFunctionList SNESList              = NULL;
108ba1e511SMatthew Knepley 
118ba1e511SMatthew Knepley /* Logging support */
1222c6f798SBarry Smith PetscClassId  SNES_CLASSID, DMSNES_CLASSID;
13fc8bc0e3SRichard Tran Mills PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval;
14a09944afSBarry Smith 
15e113a28aSBarry Smith /*@
16dc4c0fb0SBarry Smith    SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged.
17e113a28aSBarry Smith 
18c3339decSBarry Smith    Logically Collective
19e113a28aSBarry Smith 
20e113a28aSBarry Smith    Input Parameters:
21f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
22f6dfbefdSBarry Smith -  flg - `PETSC_TRUE` indicates you want the error generated
23e113a28aSBarry Smith 
2420f4b53cSBarry Smith    Options Database Key:
2567b8a455SSatish Balay .  -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge
26e113a28aSBarry Smith 
27e113a28aSBarry Smith    Level: intermediate
28e113a28aSBarry Smith 
29f6dfbefdSBarry Smith    Note:
30f6dfbefdSBarry Smith    Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()`
31f6dfbefdSBarry Smith    to determine if it has converged. Otherwise the solution may be inaccurate or wrong
32e113a28aSBarry Smith 
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 
1222fe279fdSBarry Smith    Input Parameter:
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 
1482fe279fdSBarry Smith    Input Parameter:
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:
17620f4b53cSBarry 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 
1992fe279fdSBarry Smith    Input Parameter:
200f6dfbefdSBarry Smith .  snes - the `SNES` context
2018383d7d7SFande Kong 
2022fe279fdSBarry Smith    Output Parameter:
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 
2232fe279fdSBarry Smith    Input Parameter:
224f6dfbefdSBarry Smith .  snes - the `SNES` context
2256a388c36SPeter Brune 
2262fe279fdSBarry Smith    Output Parameter:
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 
2472fe279fdSBarry Smith    Input Parameter:
248f6dfbefdSBarry Smith .  snes - the `SNES` context
24907b62357SFande Kong 
2502fe279fdSBarry Smith    Output Parameter:
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:
71120f4b53cSBarry 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 
852a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
853d71ae5a4SJacob Faibussowitsch {
854a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
855a4598233SStefano Zampini 
8560f0abf79SStefano Zampini   PetscFunctionBegin;
8570f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
858a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
859a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
860a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
861a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
862a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
863a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
8640f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
865a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
8660f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8670f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8680f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8690f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8700f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8710f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8720f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8730f0abf79SStefano Zampini   PetscOptionsEnd();
8743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8750f0abf79SStefano Zampini }
8760f0abf79SStefano Zampini 
8779b94acceSBarry Smith /*@
878f6dfbefdSBarry Smith    SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
8799b94acceSBarry Smith 
880c3339decSBarry Smith    Collective
881c7afd0dbSLois Curfman McInnes 
8829b94acceSBarry Smith    Input Parameter:
883f6dfbefdSBarry Smith .  snes - the `SNES` context
8849b94acceSBarry Smith 
88536851e7fSLois Curfman McInnes    Options Database Keys:
886f6dfbefdSBarry Smith +  -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
88782738288SBarry Smith .  -snes_stol - convergence tolerance in terms of the norm
88882738288SBarry Smith                 of the change in the solution between steps
88970441072SBarry Smith .  -snes_atol <abstol> - absolute tolerance of residual norm
890b39c3a46SLois Curfman McInnes .  -snes_rtol <rtol> - relative decrease in tolerance norm from initial
891e4d06f11SPatrick Farrell .  -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
892be5caee7SBarry Smith .  -snes_force_iteration <force> - force SNESSolve() to take at least one iteration
893b39c3a46SLois Curfman McInnes .  -snes_max_it <max_it> - maximum number of iterations
894b39c3a46SLois Curfman McInnes .  -snes_max_funcs <max_funcs> - maximum number of function evaluations
8954839bfe8SBarry Smith .  -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
896ddf469c8SBarry Smith .  -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops
897a8054027SBarry Smith .  -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild)
8983d5a8a6aSBarry Smith .  -snes_lag_preconditioner_persists <true,false> - retains the -snes_lag_preconditioner information across multiple SNESSolve()
899e35cf81dSBarry Smith .  -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild)
9003d5a8a6aSBarry Smith .  -snes_lag_jacobian_persists <true,false> - retains the -snes_lag_jacobian information across multiple SNESSolve()
9014a221d59SStefano Zampini .  -snes_tr_tol <trtol> - trust region tolerance
902f362779dSJed Brown .  -snes_convergence_test - <default,skip,correct_pressure> convergence test in nonlinear solver.
903f6dfbefdSBarry Smith                                default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense
904f6dfbefdSBarry Smith                                of convergence test. correct_pressure S`NESConvergedCorrectPressure()` has special handling of a pressure null space.
905fde5950dSBarry Smith .  -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout
906fde5950dSBarry Smith .  -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration
907fde5950dSBarry Smith .  -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration
908fde5950dSBarry Smith .  -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9094619e776SBarry Smith .  -snes_monitor_lg_residualnorm - plots residual norm at each iteration
910459f5d12SBarry Smith .  -snes_monitor_lg_range - plots residual norm at each iteration
9115e7c47f3SMatthew G. Knepley .  -snes_monitor_pause_final - Pauses all monitor drawing after the solver ends
912e24b481bSBarry Smith .  -snes_fd - use finite differences to compute Jacobian; very slow, only for testing
913e2e60de9SPeter Brune .  -snes_fd_color - use finite differences with coloring to compute Jacobian
9145968eb51SBarry Smith .  -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration
915b5badacbSBarry Smith .  -snes_converged_reason - print the reason for convergence/divergence after each solve
916e62ac41dSBarry Smith .  -npc_snes_type <type> - the SNES type to use as a nonlinear preconditioner
917e62ac41dSBarry 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.
918e62ac41dSBarry 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.
91982738288SBarry Smith 
920f6dfbefdSBarry Smith     Options Database Keys for Eisenstat-Walker method:
921fa9f3622SBarry Smith +  -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
9224b27c08aSLois Curfman McInnes .  -snes_ksp_ew_version ver - version of  Eisenstat-Walker method
92336851e7fSLois Curfman McInnes .  -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
92436851e7fSLois Curfman McInnes .  -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
92536851e7fSLois Curfman McInnes .  -snes_ksp_ew_gamma <gamma> - Sets gamma
92636851e7fSLois Curfman McInnes .  -snes_ksp_ew_alpha <alpha> - Sets alpha
92736851e7fSLois Curfman McInnes .  -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
92836851e7fSLois Curfman McInnes -  -snes_ksp_ew_threshold <threshold> - Sets threshold
92982738288SBarry Smith 
930dc4c0fb0SBarry Smith    Level: beginner
931dc4c0fb0SBarry Smith 
93211ca99fdSLois Curfman McInnes    Notes:
933ec5066bdSBarry Smith    To see all options, run your program with the -help option or consult the users manual
934ec5066bdSBarry Smith 
935f6dfbefdSBarry Smith    `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix free, and computing explicitly with
936f6dfbefdSBarry Smith    finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
93783e2fdc7SBarry Smith 
938dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`
9399b94acceSBarry Smith @*/
940d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
941d71ae5a4SJacob Faibussowitsch {
9428afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
943d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
94404d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
945649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
94685385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9470f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
948c40d0f55SPeter Brune   PCSide      pcside;
949a64e098fSPeter Brune   const char *optionsprefix;
9509b94acceSBarry Smith 
9513a40ed3dSBarry Smith   PetscFunctionBegin;
9520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9539566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
954d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
955639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
957d64ed03dSBarry Smith   if (flg) {
9589566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9597adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9609566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
961d64ed03dSBarry Smith   }
9629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
9639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
964186905e3SBarry Smith 
9659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
9669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
9679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
9689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
9699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
9709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
9719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
9729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
9739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
97485385478SLisandro Dalcin 
9759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
976a8054027SBarry Smith   if (flg) {
9775f80ce2aSJacob Faibussowitsch     PetscCheck(lag != -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_USER, "Cannot set the lag to -1 from the command line since the preconditioner must be built as least once, perhaps you mean -2");
9789566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
979a8054027SBarry Smith   }
9809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
9811baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
9829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
983e35cf81dSBarry Smith   if (flg) {
9845f80ce2aSJacob 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");
9859566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
986e35cf81dSBarry Smith   }
9879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
9881baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
98937ec4e1aSPeter Brune 
9909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
9911baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
992a8054027SBarry Smith 
9939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, sizeof(convtests) / sizeof(char *), "default", &indx, &flg));
99485385478SLisandro Dalcin   if (flg) {
99585385478SLisandro Dalcin     switch (indx) {
996d71ae5a4SJacob Faibussowitsch     case 0:
997d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
998d71ae5a4SJacob Faibussowitsch       break;
999d71ae5a4SJacob Faibussowitsch     case 1:
1000d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1001d71ae5a4SJacob Faibussowitsch       break;
1002d71ae5a4SJacob Faibussowitsch     case 2:
1003d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1004d71ae5a4SJacob Faibussowitsch       break;
100585385478SLisandro Dalcin     }
100685385478SLisandro Dalcin   }
100785385478SLisandro Dalcin 
10089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10099566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1010fdacfa88SPeter Brune 
10119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10129566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1013186905e3SBarry Smith 
101485385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
101585385478SLisandro Dalcin 
10169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1017186905e3SBarry Smith 
10180f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10190f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1020a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1021186905e3SBarry Smith 
102290d69ab7SBarry Smith   flg = PETSC_FALSE;
10239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10249566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1025eabae89aSBarry Smith 
10269566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10279566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10289566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1029eabae89aSBarry Smith 
10309566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10319566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10329566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10339566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10349566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10359566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10369566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10382db13446SMatthew G. Knepley 
10399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10409566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10415180491cSLisandro Dalcin 
104290d69ab7SBarry Smith   flg = PETSC_FALSE;
10439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1044459f5d12SBarry Smith   if (flg) {
1045459f5d12SBarry Smith     PetscViewer ctx;
1046e24b481bSBarry Smith 
10479566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10489566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1049459f5d12SBarry Smith   }
10502e7541e6SPeter Brune 
105190d69ab7SBarry Smith   flg = PETSC_FALSE;
10529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10539566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1054c4421ceaSFande Kong 
1055c4421ceaSFande Kong   flg = PETSC_FALSE;
10569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10574b27c08aSLois Curfman McInnes   if (flg) {
10586cab3a1bSJed Brown     void *functx;
1059b1f624c7SBarry Smith     DM    dm;
10609566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1061800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10629566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10639566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10649566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
10659b94acceSBarry Smith   }
1066639f9d9dSBarry Smith 
106744848bc4SPeter Brune   flg = PETSC_FALSE;
10689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
10691baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
107097584545SPeter Brune 
107197584545SPeter Brune   flg = PETSC_FALSE;
10729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
107344848bc4SPeter Brune   if (flg) {
1074c52e227fSPeter Brune     DM dm;
10759566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1076800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10779566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
10789566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
107944848bc4SPeter Brune   }
108044848bc4SPeter Brune 
1081aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1083d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1084a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1085d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1086a8248277SBarry Smith   }
1087aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
10889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1089d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
10909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1091d28543b3SPeter Brune 
1092c40d0f55SPeter Brune   flg = PETSC_FALSE;
10939566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
10949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
10959566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1096c40d0f55SPeter Brune 
1097e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
10988a70d858SHong Zhang   /*
10998a70d858SHong Zhang     Publish convergence information using SAWs
11008a70d858SHong Zhang   */
11018a70d858SHong Zhang   flg = PETSC_FALSE;
11029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11038a70d858SHong Zhang   if (flg) {
11048a70d858SHong Zhang     void *ctx;
11059566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11069566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11078a70d858SHong Zhang   }
11088a70d858SHong Zhang #endif
11098a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1110b90c6cbeSBarry Smith   {
1111b90c6cbeSBarry Smith     PetscBool set;
1112b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11139566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11141baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1115b90c6cbeSBarry Smith   }
1116b90c6cbeSBarry Smith #endif
1117b90c6cbeSBarry Smith 
111848a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
111976b2cf59SMatthew Knepley 
1120dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11215d973c19SBarry Smith 
11225d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1123dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1124d0609cedSBarry Smith   PetscOptionsEnd();
11254bbc92c1SBarry Smith 
1126d8d34be6SBarry Smith   if (snes->linesearch) {
11279566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11289566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1129d8d34be6SBarry Smith   }
11309e764e56SPeter Brune 
11316aa5e7e9SBarry Smith   if (snes->usesksp) {
11329566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11339566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11349566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11356aa5e7e9SBarry Smith   }
11366991f827SBarry Smith 
1137b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11389566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
114048a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11411baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1142b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1144b3cd9a81SMatthew G. Knepley }
1145b3cd9a81SMatthew G. Knepley 
1146b3cd9a81SMatthew G. Knepley /*@
1147f6dfbefdSBarry Smith    SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously set from options
1148b3cd9a81SMatthew G. Knepley 
1149c3339decSBarry Smith    Collective
1150b3cd9a81SMatthew G. Knepley 
1151b3cd9a81SMatthew G. Knepley    Input Parameter:
1152f6dfbefdSBarry Smith .  snes - the `SNES` context
1153b3cd9a81SMatthew G. Knepley 
1154b3cd9a81SMatthew G. Knepley    Level: beginner
1155b3cd9a81SMatthew G. Knepley 
1156dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1157b3cd9a81SMatthew G. Knepley @*/
1158d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1159d71ae5a4SJacob Faibussowitsch {
1160b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11619566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11639b94acceSBarry Smith }
11649b94acceSBarry Smith 
1165bb9467b5SJed Brown /*@C
1166d25893d9SBarry Smith    SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1167d25893d9SBarry Smith    the nonlinear solvers.
1168d25893d9SBarry Smith 
1169dc4c0fb0SBarry Smith    Logically Collective; No Fortran Support
1170d25893d9SBarry Smith 
1171d25893d9SBarry Smith    Input Parameters:
1172f6dfbefdSBarry Smith +  snes - the `SNES` context
1173d25893d9SBarry Smith .  compute - function to compute the context
1174d25893d9SBarry Smith -  destroy - function to destroy the context
1175d25893d9SBarry Smith 
1176d25893d9SBarry Smith    Level: intermediate
1177d25893d9SBarry Smith 
1178f6dfbefdSBarry Smith    Note:
1179f6dfbefdSBarry Smith    This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1180f6dfbefdSBarry Smith 
1181f6dfbefdSBarry Smith    Use `SNESSetApplicationContext()` to see the context immediately
1182f6dfbefdSBarry Smith 
1183dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetApplicationContext()`, `SNESSetComputeApplicationContext()`, `SNESSetApplicationContext()`
1184d25893d9SBarry Smith @*/
1185d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES, void **), PetscErrorCode (*destroy)(void **))
1186d71ae5a4SJacob Faibussowitsch {
1187d25893d9SBarry Smith   PetscFunctionBegin;
1188d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1189d25893d9SBarry Smith   snes->ops->usercompute = compute;
1190d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
11913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1192d25893d9SBarry Smith }
1193a847f771SSatish Balay 
1194b07ff414SBarry Smith /*@
1195f6dfbefdSBarry Smith    SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
11969b94acceSBarry Smith 
1197c3339decSBarry Smith    Logically Collective
1198fee21e36SBarry Smith 
1199c7afd0dbSLois Curfman McInnes    Input Parameters:
1200f6dfbefdSBarry Smith +  snes - the `SNES` context
1201c7afd0dbSLois Curfman McInnes -  usrP - optional user context
1202c7afd0dbSLois Curfman McInnes 
120336851e7fSLois Curfman McInnes    Level: intermediate
120436851e7fSLois Curfman McInnes 
1205f6dfbefdSBarry Smith    Notes:
1206f6dfbefdSBarry Smith    Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1207f6dfbefdSBarry Smith    with `SNESGetApplicationContext()`
1208f6dfbefdSBarry Smith 
1209f6dfbefdSBarry Smith    To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1210f6dfbefdSBarry Smith 
1211f6dfbefdSBarry Smith    Fortran Note:
1212dc4c0fb0SBarry Smith     You must write a Fortran interface definition for this
1213daf670e6SBarry Smith     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1214daf670e6SBarry Smith 
1215dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12169b94acceSBarry Smith @*/
1217d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1218d71ae5a4SJacob Faibussowitsch {
1219b07ff414SBarry Smith   KSP ksp;
12201b2093e4SBarry Smith 
12213a40ed3dSBarry Smith   PetscFunctionBegin;
12220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12239566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12249566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12259b94acceSBarry Smith   snes->user = usrP;
12263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12279b94acceSBarry Smith }
122874679c65SBarry Smith 
1229b07ff414SBarry Smith /*@
12309b94acceSBarry Smith    SNESGetApplicationContext - Gets the user-defined context for the
1231f6dfbefdSBarry Smith    nonlinear solvers set with `SNESGetApplicationContext()` or with `SNESSetComputeApplicationContext()`
12329b94acceSBarry Smith 
1233c7afd0dbSLois Curfman McInnes    Not Collective
1234c7afd0dbSLois Curfman McInnes 
12359b94acceSBarry Smith    Input Parameter:
1236f6dfbefdSBarry Smith .  snes - `SNES` context
12379b94acceSBarry Smith 
12389b94acceSBarry Smith    Output Parameter:
12399b94acceSBarry Smith .  usrP - user context
12409b94acceSBarry Smith 
124136851e7fSLois Curfman McInnes    Level: intermediate
124236851e7fSLois Curfman McInnes 
1243dc4c0fb0SBarry Smith    Fortran Note:
1244dc4c0fb0SBarry Smith    You must write a Fortran interface definition for this
1245dc4c0fb0SBarry Smith    function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1246dc4c0fb0SBarry Smith 
1247dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetApplicationContext()`
12489b94acceSBarry Smith @*/
1249d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1250d71ae5a4SJacob Faibussowitsch {
12513a40ed3dSBarry Smith   PetscFunctionBegin;
12520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1253e71120c6SJed Brown   *(void **)usrP = snes->user;
12543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12559b94acceSBarry Smith }
125674679c65SBarry Smith 
12579b94acceSBarry Smith /*@
1258f6dfbefdSBarry Smith    SNESSetUseMatrixFree - indicates that `SNES` should use matrix free finite difference matrix vector products to apply the Jacobian.
12593565c898SBarry Smith 
1260dc4c0fb0SBarry Smith    Logically Collective
12613565c898SBarry Smith 
12623565c898SBarry Smith    Input Parameters:
1263f6dfbefdSBarry Smith +  snes - `SNES` context
1264f6dfbefdSBarry Smith .  mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1265f6dfbefdSBarry 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
1266f6dfbefdSBarry Smith    this option no matrix element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
12673565c898SBarry Smith 
1268f6dfbefdSBarry Smith    Options Database Keys:
1269f6dfbefdSBarry Smith + -snes_mf_operator - use matrix free only for the mat operator
1270f6dfbefdSBarry Smith . -snes_mf - use matrix-free for both the mat and pmat operator
1271ec5066bdSBarry Smith . -snes_fd_color - compute the Jacobian via coloring and finite differences.
1272ec5066bdSBarry Smith - -snes_fd - compute the Jacobian via finite differences (slow)
12733565c898SBarry Smith 
12743565c898SBarry Smith    Level: intermediate
12753565c898SBarry Smith 
1276f6dfbefdSBarry Smith    Note:
1277dc4c0fb0SBarry Smith    `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free, and computing explicitly with
1278f6dfbefdSBarry Smith    finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1279ec5066bdSBarry Smith 
1280dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`
12813565c898SBarry Smith @*/
1282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1283d71ae5a4SJacob Faibussowitsch {
12843565c898SBarry Smith   PetscFunctionBegin;
12853565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
128688b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
128788b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
12884ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
12893565c898SBarry Smith   snes->mf_operator = mf_operator;
12903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12913565c898SBarry Smith }
12923565c898SBarry Smith 
12933565c898SBarry Smith /*@
1294dc4c0fb0SBarry Smith    SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
12953565c898SBarry Smith 
1296f6dfbefdSBarry Smith    Not Collective, but the resulting flags will be the same on all MPI ranks
12973565c898SBarry Smith 
12983565c898SBarry Smith    Input Parameter:
1299f6dfbefdSBarry Smith .  snes - `SNES` context
13003565c898SBarry Smith 
13013565c898SBarry Smith    Output Parameters:
1302f6dfbefdSBarry Smith +  mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1303f6dfbefdSBarry 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
13043565c898SBarry Smith 
13053565c898SBarry Smith    Level: intermediate
13063565c898SBarry Smith 
1307dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13083565c898SBarry Smith @*/
1309d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1310d71ae5a4SJacob Faibussowitsch {
13113565c898SBarry Smith   PetscFunctionBegin;
13123565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13133565c898SBarry Smith   if (mf) *mf = snes->mf;
13143565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13163565c898SBarry Smith }
13173565c898SBarry Smith 
13183565c898SBarry Smith /*@
1319c8228a4eSBarry Smith    SNESGetIterationNumber - Gets the number of nonlinear iterations completed
1320c8228a4eSBarry Smith    at this time.
13219b94acceSBarry Smith 
1322c7afd0dbSLois Curfman McInnes    Not Collective
1323c7afd0dbSLois Curfman McInnes 
13249b94acceSBarry Smith    Input Parameter:
1325f6dfbefdSBarry Smith .  snes - `SNES` context
13269b94acceSBarry Smith 
13279b94acceSBarry Smith    Output Parameter:
13289b94acceSBarry Smith .  iter - iteration number
13299b94acceSBarry Smith 
1330dc4c0fb0SBarry Smith    Level: intermediate
1331dc4c0fb0SBarry Smith 
1332c8228a4eSBarry Smith    Notes:
1333c8228a4eSBarry Smith    For example, during the computation of iteration 2 this would return 1.
1334c8228a4eSBarry Smith 
1335c8228a4eSBarry Smith    This is useful for using lagged Jacobians (where one does not recompute the
1336f6dfbefdSBarry Smith    Jacobian at each `SNES` iteration). For example, the code
133708405cd6SLois Curfman McInnes .vb
133808405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
133908405cd6SLois Curfman McInnes       if (!(it % 2)) {
134008405cd6SLois Curfman McInnes         [compute Jacobian here]
134108405cd6SLois Curfman McInnes       }
134208405cd6SLois Curfman McInnes .ve
1343f6dfbefdSBarry Smith    can be used in your function that computes the Jacobian to cause the Jacobian to be
1344f6dfbefdSBarry Smith    recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1345c8228a4eSBarry Smith 
1346f6dfbefdSBarry Smith    After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1347c04deec6SBarry Smith 
1348dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`
13499b94acceSBarry Smith @*/
1350d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1351d71ae5a4SJacob Faibussowitsch {
13523a40ed3dSBarry Smith   PetscFunctionBegin;
13530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13544482741eSBarry Smith   PetscValidIntPointer(iter, 2);
13559b94acceSBarry Smith   *iter = snes->iter;
13563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13579b94acceSBarry Smith }
135874679c65SBarry Smith 
1359360c497dSPeter Brune /*@
1360360c497dSPeter Brune    SNESSetIterationNumber - Sets the current iteration number.
1361360c497dSPeter Brune 
1362360c497dSPeter Brune    Not Collective
1363360c497dSPeter Brune 
1364d8d19677SJose E. Roman    Input Parameters:
1365f6dfbefdSBarry Smith +  snes - `SNES` context
1366a2b725a8SWilliam Gropp -  iter - iteration number
1367360c497dSPeter Brune 
1368360c497dSPeter Brune    Level: developer
1369360c497dSPeter Brune 
1370dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetLinearSolveIterations()`
1371360c497dSPeter Brune @*/
1372d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1373d71ae5a4SJacob Faibussowitsch {
1374360c497dSPeter Brune   PetscFunctionBegin;
1375360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13769566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1377360c497dSPeter Brune   snes->iter = iter;
13789566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
13793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1380360c497dSPeter Brune }
1381360c497dSPeter Brune 
13829b94acceSBarry Smith /*@
1383b850b91aSLisandro Dalcin    SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
13849b94acceSBarry Smith    attempted by the nonlinear solver.
13859b94acceSBarry Smith 
1386c7afd0dbSLois Curfman McInnes    Not Collective
1387c7afd0dbSLois Curfman McInnes 
13889b94acceSBarry Smith    Input Parameter:
1389f6dfbefdSBarry Smith .  snes - `SNES` context
13909b94acceSBarry Smith 
13919b94acceSBarry Smith    Output Parameter:
13929b94acceSBarry Smith .  nfails - number of unsuccessful steps attempted
13939b94acceSBarry Smith 
1394dc4c0fb0SBarry Smith    Level: intermediate
1395dc4c0fb0SBarry Smith 
1396f6dfbefdSBarry Smith    Note:
1397f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()`.
1398c96a6f78SLois Curfman McInnes 
1399dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1400db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14019b94acceSBarry Smith @*/
1402d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1403d71ae5a4SJacob Faibussowitsch {
14043a40ed3dSBarry Smith   PetscFunctionBegin;
14050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14064482741eSBarry Smith   PetscValidIntPointer(nfails, 2);
140750ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
140950ffb88aSMatthew Knepley }
141050ffb88aSMatthew Knepley 
141150ffb88aSMatthew Knepley /*@
1412b850b91aSLisandro Dalcin    SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1413f6dfbefdSBarry Smith    attempted by the nonlinear solver before it gives up and generates an error
141450ffb88aSMatthew Knepley 
141550ffb88aSMatthew Knepley    Not Collective
141650ffb88aSMatthew Knepley 
141750ffb88aSMatthew Knepley    Input Parameters:
1418f6dfbefdSBarry Smith +  snes     - `SNES` context
141950ffb88aSMatthew Knepley -  maxFails - maximum of unsuccessful steps
142050ffb88aSMatthew Knepley 
142150ffb88aSMatthew Knepley    Level: intermediate
142250ffb88aSMatthew Knepley 
1423dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1424db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
142550ffb88aSMatthew Knepley @*/
1426d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1427d71ae5a4SJacob Faibussowitsch {
142850ffb88aSMatthew Knepley   PetscFunctionBegin;
14290700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
143050ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
14313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143250ffb88aSMatthew Knepley }
143350ffb88aSMatthew Knepley 
143450ffb88aSMatthew Knepley /*@
1435b850b91aSLisandro Dalcin    SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1436f6dfbefdSBarry Smith    attempted by the nonlinear solver before it gives up and generates an error
143750ffb88aSMatthew Knepley 
143850ffb88aSMatthew Knepley    Not Collective
143950ffb88aSMatthew Knepley 
144050ffb88aSMatthew Knepley    Input Parameter:
144120f4b53cSBarry Smith .  snes     - `SNES` context
144250ffb88aSMatthew Knepley 
144350ffb88aSMatthew Knepley    Output Parameter:
144450ffb88aSMatthew Knepley .  maxFails - maximum of unsuccessful steps
144550ffb88aSMatthew Knepley 
144650ffb88aSMatthew Knepley    Level: intermediate
144750ffb88aSMatthew Knepley 
1448dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1449db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
145050ffb88aSMatthew Knepley @*/
1451d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1452d71ae5a4SJacob Faibussowitsch {
145350ffb88aSMatthew Knepley   PetscFunctionBegin;
14540700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14554482741eSBarry Smith   PetscValidIntPointer(maxFails, 2);
145650ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
14573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14589b94acceSBarry Smith }
1459a847f771SSatish Balay 
14602541af92SBarry Smith /*@
14612541af92SBarry Smith    SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1462f6dfbefdSBarry Smith      done by the `SNES` object
14632541af92SBarry Smith 
14642541af92SBarry Smith    Not Collective
14652541af92SBarry Smith 
14662541af92SBarry Smith    Input Parameter:
1467f6dfbefdSBarry Smith .  snes     - `SNES` context
14682541af92SBarry Smith 
14692541af92SBarry Smith    Output Parameter:
14702541af92SBarry Smith .  nfuncs - number of evaluations
14712541af92SBarry Smith 
14722541af92SBarry Smith    Level: intermediate
14732541af92SBarry Smith 
1474f6dfbefdSBarry Smith    Note:
1475f6dfbefdSBarry Smith     Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1476971e163fSPeter Brune 
1477dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
14782541af92SBarry Smith @*/
1479d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1480d71ae5a4SJacob Faibussowitsch {
14812541af92SBarry Smith   PetscFunctionBegin;
14820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14832541af92SBarry Smith   PetscValidIntPointer(nfuncs, 2);
14842541af92SBarry Smith   *nfuncs = snes->nfuncs;
14853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14862541af92SBarry Smith }
14872541af92SBarry Smith 
14883d4c4710SBarry Smith /*@
14893d4c4710SBarry Smith    SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
14903d4c4710SBarry Smith    linear solvers.
14913d4c4710SBarry Smith 
14923d4c4710SBarry Smith    Not Collective
14933d4c4710SBarry Smith 
14943d4c4710SBarry Smith    Input Parameter:
1495f6dfbefdSBarry Smith .  snes - `SNES` context
14963d4c4710SBarry Smith 
14973d4c4710SBarry Smith    Output Parameter:
14983d4c4710SBarry Smith .  nfails - number of failed solves
14993d4c4710SBarry Smith 
1500f6dfbefdSBarry Smith    Options Database Key:
15019d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15029d85da0cSMatthew G. Knepley 
1503f6dfbefdSBarry Smith    Level: intermediate
1504f6dfbefdSBarry Smith 
1505f6dfbefdSBarry Smith    Note:
1506f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()`.
15073d4c4710SBarry Smith 
1508dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15093d4c4710SBarry Smith @*/
1510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1511d71ae5a4SJacob Faibussowitsch {
15123d4c4710SBarry Smith   PetscFunctionBegin;
15130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15143d4c4710SBarry Smith   PetscValidIntPointer(nfails, 2);
15153d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15173d4c4710SBarry Smith }
15183d4c4710SBarry Smith 
15193d4c4710SBarry Smith /*@
15203d4c4710SBarry Smith    SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1521f6dfbefdSBarry Smith    allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15223d4c4710SBarry Smith 
1523c3339decSBarry Smith    Logically Collective
15243d4c4710SBarry Smith 
15253d4c4710SBarry Smith    Input Parameters:
1526f6dfbefdSBarry Smith +  snes     - `SNES` context
15273d4c4710SBarry Smith -  maxFails - maximum allowed linear solve failures
15283d4c4710SBarry Smith 
1529f6dfbefdSBarry Smith    Options Database Key:
15309d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15319d85da0cSMatthew G. Knepley 
1532dc4c0fb0SBarry Smith    Level: intermediate
1533dc4c0fb0SBarry Smith 
1534f6dfbefdSBarry Smith    Note:
1535f6dfbefdSBarry Smith     By default this is 0; that is `SNES` returns on the first failed linear solve
15363d4c4710SBarry Smith 
1537dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
15383d4c4710SBarry Smith @*/
1539d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1540d71ae5a4SJacob Faibussowitsch {
15413d4c4710SBarry Smith   PetscFunctionBegin;
15420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1543c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
15443d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
15453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15463d4c4710SBarry Smith }
15473d4c4710SBarry Smith 
15483d4c4710SBarry Smith /*@
15493d4c4710SBarry Smith    SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1550f6dfbefdSBarry Smith      are allowed before `SNES` returns as unsuccessful
15513d4c4710SBarry Smith 
15523d4c4710SBarry Smith    Not Collective
15533d4c4710SBarry Smith 
15543d4c4710SBarry Smith    Input Parameter:
1555f6dfbefdSBarry Smith .  snes     - `SNES` context
15563d4c4710SBarry Smith 
15573d4c4710SBarry Smith    Output Parameter:
15583d4c4710SBarry Smith .  maxFails - maximum of unsuccessful solves allowed
15593d4c4710SBarry Smith 
15603d4c4710SBarry Smith    Level: intermediate
15613d4c4710SBarry Smith 
1562f6dfbefdSBarry Smith    Note:
1563f6dfbefdSBarry Smith     By default this is 1; that is `SNES` returns on the first failed linear solve
15643d4c4710SBarry Smith 
1565dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
15663d4c4710SBarry Smith @*/
1567d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1568d71ae5a4SJacob Faibussowitsch {
15693d4c4710SBarry Smith   PetscFunctionBegin;
15700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15713d4c4710SBarry Smith   PetscValidIntPointer(maxFails, 2);
15723d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
15733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15743d4c4710SBarry Smith }
15753d4c4710SBarry Smith 
1576c96a6f78SLois Curfman McInnes /*@
1577b850b91aSLisandro Dalcin    SNESGetLinearSolveIterations - Gets the total number of linear iterations
1578c96a6f78SLois Curfman McInnes    used by the nonlinear solver.
1579c96a6f78SLois Curfman McInnes 
1580c7afd0dbSLois Curfman McInnes    Not Collective
1581c7afd0dbSLois Curfman McInnes 
1582c96a6f78SLois Curfman McInnes    Input Parameter:
1583f6dfbefdSBarry Smith .  snes - `SNES` context
1584c96a6f78SLois Curfman McInnes 
1585c96a6f78SLois Curfman McInnes    Output Parameter:
1586c96a6f78SLois Curfman McInnes .  lits - number of linear iterations
1587c96a6f78SLois Curfman McInnes 
1588dc4c0fb0SBarry Smith    Level: intermediate
1589dc4c0fb0SBarry Smith 
1590c96a6f78SLois Curfman McInnes    Notes:
1591f6dfbefdSBarry Smith    This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1592c96a6f78SLois Curfman McInnes 
1593f6dfbefdSBarry 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
1594f6dfbefdSBarry Smith    then call `KSPGetIterationNumber()` after the failed solve.
1595010be392SBarry Smith 
1596dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1597c96a6f78SLois Curfman McInnes @*/
1598d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1599d71ae5a4SJacob Faibussowitsch {
16003a40ed3dSBarry Smith   PetscFunctionBegin;
16010700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16024482741eSBarry Smith   PetscValidIntPointer(lits, 2);
1603c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1605c96a6f78SLois Curfman McInnes }
1606c96a6f78SLois Curfman McInnes 
1607971e163fSPeter Brune /*@
1608971e163fSPeter Brune    SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1609f6dfbefdSBarry Smith    are reset every time `SNESSolve()` is called.
1610971e163fSPeter Brune 
1611c3339decSBarry Smith    Logically Collective
1612971e163fSPeter Brune 
1613d8d19677SJose E. Roman    Input Parameters:
1614f6dfbefdSBarry Smith +  snes - `SNES` context
1615f6dfbefdSBarry Smith -  reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1616971e163fSPeter Brune 
1617971e163fSPeter Brune    Level: developer
1618971e163fSPeter Brune 
1619dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1620971e163fSPeter Brune @*/
1621d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1622d71ae5a4SJacob Faibussowitsch {
1623971e163fSPeter Brune   PetscFunctionBegin;
1624971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1625971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1626971e163fSPeter Brune   snes->counters_reset = reset;
16273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1628971e163fSPeter Brune }
1629971e163fSPeter Brune 
16302999313aSBarry Smith /*@
1631f6dfbefdSBarry Smith    SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16322999313aSBarry Smith 
1633f6dfbefdSBarry Smith    Not Collective, but the `SNES` and `KSP` objects must live on the same MPI_Comm
16342999313aSBarry Smith 
16352999313aSBarry Smith    Input Parameters:
1636f6dfbefdSBarry Smith +  snes - the `SNES` context
1637f6dfbefdSBarry Smith -  ksp - the `KSP` context
16382999313aSBarry Smith 
1639dc4c0fb0SBarry Smith    Level: developer
1640dc4c0fb0SBarry Smith 
16412999313aSBarry Smith    Notes:
1642f6dfbefdSBarry Smith    The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
16432999313aSBarry Smith    so this routine is rarely needed.
16442999313aSBarry Smith 
1645f6dfbefdSBarry Smith    The `KSP` object that is already in the `SNES` object has its reference count
16462999313aSBarry Smith    decreased by one.
16472999313aSBarry Smith 
1648dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
16492999313aSBarry Smith @*/
1650d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1651d71ae5a4SJacob Faibussowitsch {
16522999313aSBarry Smith   PetscFunctionBegin;
16530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16540700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
16552999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
16569566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
16579566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
16582999313aSBarry Smith   snes->ksp = ksp;
16593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16602999313aSBarry Smith }
16612999313aSBarry Smith 
166252baeb72SSatish Balay /*@
1663dc4c0fb0SBarry Smith    SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
16649b94acceSBarry Smith 
1665d083f849SBarry Smith    Collective
1666c7afd0dbSLois Curfman McInnes 
1667f6dfbefdSBarry Smith    Input Parameter:
1668906ed7ccSBarry Smith .  comm - MPI communicator
16699b94acceSBarry Smith 
16709b94acceSBarry Smith    Output Parameter:
167120f4b53cSBarry Smith .  outsnes - the new `SNES` context
16729b94acceSBarry Smith 
1673c7afd0dbSLois Curfman McInnes    Options Database Keys:
1674dc4c0fb0SBarry Smith +   -snes_mf - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1675dc4c0fb0SBarry Smith .   -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1676dc4c0fb0SBarry Smith                as set by `SNESSetJacobian()`
1677dc4c0fb0SBarry Smith .   -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1678c7afd0dbSLois Curfman McInnes -   -snes_fd - Uses (slow!) finite differences to compute Jacobian
1679c1f60f51SBarry Smith 
168036851e7fSLois Curfman McInnes    Level: beginner
168136851e7fSLois Curfman McInnes 
168295452b02SPatrick Sanan    Developer Notes:
1683f6dfbefdSBarry Smith    `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1684efd4aadfSBarry Smith    unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1685f6dfbefdSBarry Smith    particular method does use `KSP` and regulates if the information about the `KSP` is printed
1686f6dfbefdSBarry Smith    in `SNESView()`.
1687efd4aadfSBarry Smith 
1688f6dfbefdSBarry Smith    `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1689f6dfbefdSBarry Smith    by help messages about meaningless `SNES` options.
1690f6dfbefdSBarry Smith 
1691dc4c0fb0SBarry Smith    `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1692efd4aadfSBarry Smith 
1693dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
16949b94acceSBarry Smith @*/
1695d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1696d71ae5a4SJacob Faibussowitsch {
16979b94acceSBarry Smith   SNES       snes;
1698fa9f3622SBarry Smith   SNESKSPEW *kctx;
169937fcc0dbSBarry Smith 
17003a40ed3dSBarry Smith   PetscFunctionBegin;
1701ed1caa07SMatthew Knepley   PetscValidPointer(outsnes, 2);
17020298fd71SBarry Smith   *outsnes = NULL;
17039566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17048ba1e511SMatthew Knepley 
17059566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17067adad957SLisandro Dalcin 
17078d359177SBarry Smith   snes->ops->converged       = SNESConvergedDefault;
17082c155ee1SBarry Smith   snes->usesksp              = PETSC_TRUE;
170988976e71SPeter Brune   snes->tolerancesset        = PETSC_FALSE;
17109b94acceSBarry Smith   snes->max_its              = 50;
17119750a799SBarry Smith   snes->max_funcs            = 10000;
17129b94acceSBarry Smith   snes->norm                 = 0.0;
1713c1e67a49SFande Kong   snes->xnorm                = 0.0;
1714c1e67a49SFande Kong   snes->ynorm                = 0.0;
1715365a6726SPeter Brune   snes->normschedule         = SNES_NORM_ALWAYS;
17166c67d002SPeter Brune   snes->functype             = SNES_FUNCTION_DEFAULT;
17178ca48ce9SPierre Jolivet   snes->rtol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
1718b4874afaSBarry Smith   snes->ttol                 = 0.0;
17198ca48ce9SPierre Jolivet   snes->abstol               = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50;
17208ca48ce9SPierre Jolivet   snes->stol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
17218ca48ce9SPierre Jolivet   snes->deltatol             = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12;
1722e37c518bSBarry Smith   snes->divtol               = 1.e4;
1723e37c518bSBarry Smith   snes->rnorm0               = 0;
17249b94acceSBarry Smith   snes->nfuncs               = 0;
172550ffb88aSMatthew Knepley   snes->numFailures          = 0;
172650ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17277a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1728e35cf81dSBarry Smith   snes->lagjacobian          = 1;
172937ec4e1aSPeter Brune   snes->jac_iter             = 0;
173037ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1731a8054027SBarry Smith   snes->lagpreconditioner    = 1;
173237ec4e1aSPeter Brune   snes->pre_iter             = 0;
173337ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1734639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1735c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17369e5d0892SLisandro Dalcin   snes->data                 = NULL;
17374dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1738186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17396f24a144SLois Curfman McInnes   snes->nwork                = 0;
17409e5d0892SLisandro Dalcin   snes->work                 = NULL;
174158c9b817SLisandro Dalcin   snes->nvwork               = 0;
17429e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1743758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1744758f92a0SBarry Smith   snes->conv_hist_max        = 0;
17450298fd71SBarry Smith   snes->conv_hist            = NULL;
17460298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1747758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1748971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1749e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1750184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1751efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1752b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1753c40d0f55SPeter Brune 
1754d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1755d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1756d8f46077SPeter Brune   snes->mf_version  = 1;
1757d8f46077SPeter Brune 
17583d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
17593d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
17603d4c4710SBarry Smith 
1761349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
176276bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1763349187a7SBarry Smith 
17644fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
17654fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
17664fc747eaSLawrence Mitchell 
17679b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
17684dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1769f5af7f23SKarl Rupp 
17709b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
17719b94acceSBarry Smith   kctx->version     = 2;
17720f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
17739b94acceSBarry Smith                              this was too large for some test cases */
177475567043SBarry Smith   kctx->rtol_last   = 0.0;
17750f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
17769b94acceSBarry Smith   kctx->gamma       = 1.0;
17770f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
177871f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
17790f0abf79SStefano Zampini   kctx->threshold   = 0.1;
178075567043SBarry Smith   kctx->lresid_last = 0.0;
178175567043SBarry Smith   kctx->norm_last   = 0.0;
17829b94acceSBarry Smith 
17830f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
17840f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
17850f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
17860f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
17870f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
17880f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
17890f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
17900f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
17910f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
17920f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
17930f0abf79SStefano Zampini 
17949b94acceSBarry Smith   *outsnes = snes;
17953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17969b94acceSBarry Smith }
17979b94acceSBarry Smith 
179888f0584fSBarry Smith /*MC
1799f6dfbefdSBarry Smith     SNESFunction - Functional form used to convey the nonlinear function to `SNES` in `SNESSetFunction()`
180088f0584fSBarry Smith 
180188f0584fSBarry Smith      Synopsis:
1802411c0326SBarry Smith      #include "petscsnes.h"
1803411c0326SBarry Smith      PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
180488f0584fSBarry Smith 
1805c3339decSBarry Smith      Collective
18061843f636SBarry Smith 
180788f0584fSBarry Smith      Input Parameters:
1808f6dfbefdSBarry Smith +     snes - the `SNES` context
180988f0584fSBarry Smith .     x    - state at which to evaluate residual
1810f6dfbefdSBarry Smith -     ctx     - optional user-defined function context, passed in with `SNESSetFunction()`
181188f0584fSBarry Smith 
181288f0584fSBarry Smith      Output Parameter:
181388f0584fSBarry Smith .     f  - vector to put residual (function value)
181488f0584fSBarry Smith 
1815878cb397SSatish Balay    Level: intermediate
1816878cb397SSatish Balay 
1817dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetFunction()`, `SNESGetFunction()`
181888f0584fSBarry Smith M*/
181988f0584fSBarry Smith 
18209b94acceSBarry Smith /*@C
18219b94acceSBarry Smith    SNESSetFunction - Sets the function evaluation routine and function
1822f6dfbefdSBarry Smith    vector for use by the `SNES` routines in solving systems of nonlinear
18239b94acceSBarry Smith    equations.
18249b94acceSBarry Smith 
1825c3339decSBarry Smith    Logically Collective
1826fee21e36SBarry Smith 
1827c7afd0dbSLois Curfman McInnes    Input Parameters:
1828f6dfbefdSBarry Smith +  snes - the `SNES` context
1829dc4c0fb0SBarry Smith .  r - vector to store function values, may be `NULL`
183020f4b53cSBarry Smith .  f - function evaluation routine;  for calling sequence see `SNESFunction`
1831c7afd0dbSLois Curfman McInnes -  ctx - [optional] user-defined context for private data for the
1832dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
18339b94acceSBarry Smith 
183436851e7fSLois Curfman McInnes    Level: beginner
183536851e7fSLois Curfman McInnes 
1836dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunction`
18379b94acceSBarry Smith @*/
1838d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunction(SNES snes, Vec r, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
1839d71ae5a4SJacob Faibussowitsch {
18406cab3a1bSJed Brown   DM dm;
18416cab3a1bSJed Brown 
18423a40ed3dSBarry Smith   PetscFunctionBegin;
18430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1844d2a683ecSLisandro Dalcin   if (r) {
1845d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1846d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18479566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18489566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
184985385478SLisandro Dalcin     snes->vec_func = r;
1850d2a683ecSLisandro Dalcin   }
18519566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18529566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
185348a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18559b94acceSBarry Smith }
18569b94acceSBarry Smith 
1857e4ed7901SPeter Brune /*@C
1858e4ed7901SPeter Brune    SNESSetInitialFunction - Sets the function vector to be used as the
1859f6dfbefdSBarry Smith    initial function value at the initialization of the method.  In some
1860e4ed7901SPeter Brune    instances, the user has precomputed the function before calling
1861f6dfbefdSBarry Smith    `SNESSolve()`.  This function allows one to avoid a redundant call
1862f6dfbefdSBarry Smith    to `SNESComputeFunction()` in that case.
1863e4ed7901SPeter Brune 
1864c3339decSBarry Smith    Logically Collective
1865e4ed7901SPeter Brune 
1866e4ed7901SPeter Brune    Input Parameters:
1867f6dfbefdSBarry Smith +  snes - the `SNES` context
1868e4ed7901SPeter Brune -  f - vector to store function value
1869e4ed7901SPeter Brune 
1870dc4c0fb0SBarry Smith    Level: developer
1871dc4c0fb0SBarry Smith 
1872e4ed7901SPeter Brune    Notes:
1873e4ed7901SPeter Brune    This should not be modified during the solution procedure.
1874e4ed7901SPeter Brune 
1875f6dfbefdSBarry Smith    This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1876e4ed7901SPeter Brune 
1877dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1878e4ed7901SPeter Brune @*/
1879d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1880d71ae5a4SJacob Faibussowitsch {
1881e4ed7901SPeter Brune   Vec vec_func;
1882e4ed7901SPeter Brune 
1883e4ed7901SPeter Brune   PetscFunctionBegin;
1884e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1885e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1886e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1887efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1888902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
18893ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1890902f982fSPeter Brune   }
18919566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
18929566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1893f5af7f23SKarl Rupp 
1894217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
18953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1896e4ed7901SPeter Brune }
1897e4ed7901SPeter Brune 
1898534ebe21SPeter Brune /*@
1899f6dfbefdSBarry Smith    SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1900f6dfbefdSBarry Smith    of the `SNES` method, when norms are computed in the solving process
1901534ebe21SPeter Brune 
1902c3339decSBarry Smith    Logically Collective
1903534ebe21SPeter Brune 
1904534ebe21SPeter Brune    Input Parameters:
1905f6dfbefdSBarry Smith +  snes - the `SNES` context
1906365a6726SPeter Brune -  normschedule - the frequency of norm computation
1907534ebe21SPeter Brune 
1908517f1916SMatthew G. Knepley    Options Database Key:
190967b8a455SSatish Balay .  -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1910517f1916SMatthew G. Knepley 
1911dc4c0fb0SBarry Smith    Level: advanced
1912dc4c0fb0SBarry Smith 
1913534ebe21SPeter Brune    Notes:
1914f6dfbefdSBarry Smith    Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1915534ebe21SPeter Brune    of the nonlinear function and the taking of its norm at every iteration to
1916534ebe21SPeter Brune    even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1917f6dfbefdSBarry Smith    `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1918534ebe21SPeter Brune    may either be monitored for convergence or not.  As these are often used as nonlinear
1919534ebe21SPeter Brune    preconditioners, monitoring the norm of their error is not a useful enterprise within
1920534ebe21SPeter Brune    their solution.
1921534ebe21SPeter Brune 
1922dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1923534ebe21SPeter Brune @*/
1924d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1925d71ae5a4SJacob Faibussowitsch {
1926534ebe21SPeter Brune   PetscFunctionBegin;
1927534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1928365a6726SPeter Brune   snes->normschedule = normschedule;
19293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1930534ebe21SPeter Brune }
1931534ebe21SPeter Brune 
1932534ebe21SPeter Brune /*@
1933f6dfbefdSBarry Smith    SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1934f6dfbefdSBarry Smith    of the `SNES` method.
1935534ebe21SPeter Brune 
1936c3339decSBarry Smith    Logically Collective
1937534ebe21SPeter Brune 
1938534ebe21SPeter Brune    Input Parameters:
1939f6dfbefdSBarry Smith +  snes - the `SNES` context
1940365a6726SPeter Brune -  normschedule - the type of the norm used
1941534ebe21SPeter Brune 
1942534ebe21SPeter Brune    Level: advanced
1943534ebe21SPeter Brune 
1944dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1945534ebe21SPeter Brune @*/
1946d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1947d71ae5a4SJacob Faibussowitsch {
1948534ebe21SPeter Brune   PetscFunctionBegin;
1949534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1950365a6726SPeter Brune   *normschedule = snes->normschedule;
19513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1952534ebe21SPeter Brune }
1953534ebe21SPeter Brune 
1954c5ce4427SMatthew G. Knepley /*@
1955c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1956c5ce4427SMatthew G. Knepley 
1957c3339decSBarry Smith   Logically Collective
1958c5ce4427SMatthew G. Knepley 
1959c5ce4427SMatthew G. Knepley   Input Parameters:
1960f6dfbefdSBarry Smith +  snes - the `SNES` context
1961f6dfbefdSBarry Smith -  norm - the value of the norm
1962c5ce4427SMatthew G. Knepley 
1963c5ce4427SMatthew G. Knepley   Level: developer
1964c5ce4427SMatthew G. Knepley 
1965dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1966c5ce4427SMatthew G. Knepley @*/
1967d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1968d71ae5a4SJacob Faibussowitsch {
1969c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1970c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1971c5ce4427SMatthew G. Knepley   snes->norm = norm;
19723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1973c5ce4427SMatthew G. Knepley }
1974c5ce4427SMatthew G. Knepley 
1975c5ce4427SMatthew G. Knepley /*@
1976c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
1977c5ce4427SMatthew G. Knepley 
1978c5ce4427SMatthew G. Knepley   Not Collective
1979c5ce4427SMatthew G. Knepley 
1980c5ce4427SMatthew G. Knepley   Input Parameter:
1981f6dfbefdSBarry Smith . snes - the `SNES` context
1982c5ce4427SMatthew G. Knepley 
1983c5ce4427SMatthew G. Knepley   Output Parameter:
1984c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
1985c5ce4427SMatthew G. Knepley 
1986c5ce4427SMatthew G. Knepley   Level: developer
1987c5ce4427SMatthew G. Knepley 
1988dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1989c5ce4427SMatthew G. Knepley @*/
1990d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
1991d71ae5a4SJacob Faibussowitsch {
1992c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1993c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1994dadcf809SJacob Faibussowitsch   PetscValidRealPointer(norm, 2);
1995c5ce4427SMatthew G. Knepley   *norm = snes->norm;
19963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1997c5ce4427SMatthew G. Knepley }
1998c5ce4427SMatthew G. Knepley 
1999c1e67a49SFande Kong /*@
2000f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2001c1e67a49SFande Kong 
2002c1e67a49SFande Kong   Not Collective
2003c1e67a49SFande Kong 
2004c1e67a49SFande Kong   Input Parameter:
2005f6dfbefdSBarry Smith . snes - the `SNES` context
2006c1e67a49SFande Kong 
2007c1e67a49SFande Kong   Output Parameter:
2008c1e67a49SFande Kong . ynorm - the last computed update norm
2009c1e67a49SFande Kong 
2010c1e67a49SFande Kong   Level: developer
2011c1e67a49SFande Kong 
2012f6dfbefdSBarry Smith   Note:
2013f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2014f6dfbefdSBarry Smith 
2015dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2016c1e67a49SFande Kong @*/
2017d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2018d71ae5a4SJacob Faibussowitsch {
2019c1e67a49SFande Kong   PetscFunctionBegin;
2020c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2021dadcf809SJacob Faibussowitsch   PetscValidRealPointer(ynorm, 2);
2022c1e67a49SFande Kong   *ynorm = snes->ynorm;
20233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2024c1e67a49SFande Kong }
2025c1e67a49SFande Kong 
2026c1e67a49SFande Kong /*@
20274591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2028c1e67a49SFande Kong 
2029c1e67a49SFande Kong   Not Collective
2030c1e67a49SFande Kong 
2031c1e67a49SFande Kong   Input Parameter:
2032f6dfbefdSBarry Smith . snes - the `SNES` context
2033c1e67a49SFande Kong 
2034c1e67a49SFande Kong   Output Parameter:
2035c1e67a49SFande Kong . xnorm - the last computed solution norm
2036c1e67a49SFande Kong 
2037c1e67a49SFande Kong   Level: developer
2038c1e67a49SFande Kong 
2039dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2040c1e67a49SFande Kong @*/
2041d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2042d71ae5a4SJacob Faibussowitsch {
2043c1e67a49SFande Kong   PetscFunctionBegin;
2044c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2045dadcf809SJacob Faibussowitsch   PetscValidRealPointer(xnorm, 2);
2046c1e67a49SFande Kong   *xnorm = snes->xnorm;
20473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2048c1e67a49SFande Kong }
2049c1e67a49SFande Kong 
205047073ea2SPeter Brune /*@C
2051f6dfbefdSBarry Smith    SNESSetFunctionType - Sets the `SNESFunctionType`
2052f6dfbefdSBarry Smith    of the `SNES` method.
205347073ea2SPeter Brune 
2054c3339decSBarry Smith    Logically Collective
205547073ea2SPeter Brune 
205647073ea2SPeter Brune    Input Parameters:
2057f6dfbefdSBarry Smith +  snes - the `SNES` context
2058f6dfbefdSBarry Smith -  type - the function type
205947073ea2SPeter Brune 
206047073ea2SPeter Brune    Level: developer
206147073ea2SPeter Brune 
2062f6dfbefdSBarry Smith    Notes:
2063f6dfbefdSBarry Smith    Possible values of the function type
2064f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType`
2065f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2066f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()`
2067f6dfbefdSBarry Smith 
2068f6dfbefdSBarry Smith    Different `SNESType`s use this value in different ways
2069f6dfbefdSBarry Smith 
2070dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
207147073ea2SPeter Brune @*/
2072d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2073d71ae5a4SJacob Faibussowitsch {
207447073ea2SPeter Brune   PetscFunctionBegin;
207547073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
207647073ea2SPeter Brune   snes->functype = type;
20773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207847073ea2SPeter Brune }
207947073ea2SPeter Brune 
208047073ea2SPeter Brune /*@C
2081f6dfbefdSBarry Smith    SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
208247073ea2SPeter Brune    of the SNES method.
208347073ea2SPeter Brune 
2084c3339decSBarry Smith    Logically Collective
208547073ea2SPeter Brune 
208647073ea2SPeter Brune    Input Parameters:
2087f6dfbefdSBarry Smith +  snes - the `SNES` context
2088f6dfbefdSBarry Smith -  type - the type of the function evaluation, see `SNESSetFunctionType()`
208947073ea2SPeter Brune 
209047073ea2SPeter Brune    Level: advanced
209147073ea2SPeter Brune 
2092dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
209347073ea2SPeter Brune @*/
2094d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2095d71ae5a4SJacob Faibussowitsch {
209647073ea2SPeter Brune   PetscFunctionBegin;
209747073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
209847073ea2SPeter Brune   *type = snes->functype;
20993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2100534ebe21SPeter Brune }
2101534ebe21SPeter Brune 
2102bf388a1fSBarry Smith /*MC
2103f6dfbefdSBarry Smith     SNESNGSFunction - function used to apply a Gauss-Seidel sweep on the nonlinear function
2104bf388a1fSBarry Smith 
2105bf388a1fSBarry Smith      Synopsis:
2106aaa7dc30SBarry Smith      #include <petscsnes.h>
2107be95d8f1SBarry Smith $    SNESNGSFunction(SNES snes,Vec x,Vec b,void *ctx);
2108bf388a1fSBarry Smith 
2109c3339decSBarry Smith      Collective
21101843f636SBarry Smith 
21111843f636SBarry Smith      Input Parameters:
2112bf388a1fSBarry Smith +  X   - solution vector
2113bf388a1fSBarry Smith .  B   - RHS vector
2114bf388a1fSBarry Smith -  ctx - optional user-defined Gauss-Seidel context
2115bf388a1fSBarry Smith 
21161843f636SBarry Smith      Output Parameter:
21171843f636SBarry Smith .  X   - solution vector
21181843f636SBarry Smith 
2119878cb397SSatish Balay    Level: intermediate
2120878cb397SSatish Balay 
2121dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESNGS`, `SNESSetNGS()`, `SNESGetNGS()`
2122bf388a1fSBarry Smith M*/
2123bf388a1fSBarry Smith 
2124c79ef259SPeter Brune /*@C
2125be95d8f1SBarry Smith    SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2126c79ef259SPeter Brune    use with composed nonlinear solvers.
2127c79ef259SPeter Brune 
2128c79ef259SPeter Brune    Input Parameters:
2129dc4c0fb0SBarry Smith +  snes   - the `SNES` context
2130f6dfbefdSBarry Smith .  f - function evaluation routine to apply Gauss-Seidel see `SNESNGSFunction`
2131c79ef259SPeter Brune -  ctx    - [optional] user-defined context for private data for the
2132dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2133c79ef259SPeter Brune 
213420f4b53cSBarry Smith    Calling sequence of `f`:
213520f4b53cSBarry Smith $  PetscErrorCode f(SNES snes, Vec X, Vec B, void *ctx)
2136f6dfbefdSBarry Smith +  snes - the `SNES` context
2137f6dfbefdSBarry Smith .  X - the current solution
2138dc4c0fb0SBarry Smith .  B - the right hand side vector (which may be `NULL`)
2139f6dfbefdSBarry Smith -  ctx - a user provided context
2140f6dfbefdSBarry Smith 
2141dc4c0fb0SBarry Smith    Level: intermediate
2142dc4c0fb0SBarry Smith 
2143f6dfbefdSBarry Smith    Note:
2144f6dfbefdSBarry Smith    The `SNESNGS` routines are used by the composed nonlinear solver to generate
2145f6dfbefdSBarry Smith     a problem appropriate update to the solution, particularly `SNESFAS`.
2146c79ef259SPeter Brune 
2147dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetNGS()`, `SNESNGSFunction`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`
2148c79ef259SPeter Brune @*/
2149d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNGS(SNES snes, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
2150d71ae5a4SJacob Faibussowitsch {
21516cab3a1bSJed Brown   DM dm;
21526cab3a1bSJed Brown 
2153646217ecSPeter Brune   PetscFunctionBegin;
21546cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21559566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21569566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2158646217ecSPeter Brune }
2159646217ecSPeter Brune 
2160bbc1464cSBarry Smith /*
2161bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2162bbc1464cSBarry Smith    changed during the KSPSolve()
2163bbc1464cSBarry Smith */
2164d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2165d71ae5a4SJacob Faibussowitsch {
2166bbc1464cSBarry Smith   DM     dm;
2167bbc1464cSBarry Smith   DMSNES sdm;
2168bbc1464cSBarry Smith 
2169bbc1464cSBarry Smith   PetscFunctionBegin;
21709566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21719566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2172bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2173bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2174792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21759566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21760df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2177ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2178792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21799566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2180bbc1464cSBarry Smith   } else {
2181792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21829566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2183bbc1464cSBarry Smith   }
21843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2185bbc1464cSBarry Smith }
2186bbc1464cSBarry Smith 
2187d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2188d71ae5a4SJacob Faibussowitsch {
2189e03ab78fSPeter Brune   DM     dm;
2190942e3340SBarry Smith   DMSNES sdm;
21916cab3a1bSJed Brown 
21928b0a5094SBarry Smith   PetscFunctionBegin;
21939566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21949566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
21958b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2196bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2197792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21989566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2199792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22009566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2201bbc1464cSBarry Smith   } else {
2202792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22039566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2204bbc1464cSBarry Smith   }
22053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22068b0a5094SBarry Smith }
22078b0a5094SBarry Smith 
2208d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2209d71ae5a4SJacob Faibussowitsch {
22108b0a5094SBarry Smith   PetscFunctionBegin;
2211e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2212bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22139566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22149566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22168b0a5094SBarry Smith }
22178b0a5094SBarry Smith 
22188b0a5094SBarry Smith /*@C
2219f6dfbefdSBarry Smith    SNESSetPicard - Use `SNES` to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization)
22208b0a5094SBarry Smith 
2221c3339decSBarry Smith    Logically Collective
22228b0a5094SBarry Smith 
22238b0a5094SBarry Smith    Input Parameters:
2224f6dfbefdSBarry Smith +  snes - the `SNES` context
2225dc4c0fb0SBarry Smith .  r - vector to store function values, may be `NULL`
2226dc4c0fb0SBarry Smith .  bp - function evaluation routine, may be `NULL`
22276b7fb656SBarry Smith .  Amat - matrix with which A(x) x - bp(x) - b is to be computed
2228dc4c0fb0SBarry Smith .  Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
222920f4b53cSBarry Smith .  J  - function to compute matrix values, for the calling sequence see `SNESJacobianFunction()`
2230dc4c0fb0SBarry Smith -  ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2231dc4c0fb0SBarry Smith 
2232dc4c0fb0SBarry Smith    Level: intermediate
22338b0a5094SBarry Smith 
22348b0a5094SBarry Smith    Notes:
22356b7fb656SBarry Smith     It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2236f450aa47SBarry 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.
2237f450aa47SBarry Smith 
2238f6dfbefdSBarry Smith     One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22398b0a5094SBarry Smith 
2240dc4c0fb0SBarry 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}.
2241dc4c0fb0SBarry Smith      When an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration.
22428b0a5094SBarry Smith 
2243dc4c0fb0SBarry Smith      Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22448b0a5094SBarry Smith 
22450d04baf8SBarry Smith    We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22466b7fb656SBarry Smith    the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b
22478b0a5094SBarry Smith 
22488b0a5094SBarry 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
22498b0a5094SBarry 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
22508b0a5094SBarry Smith    different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
22518b0a5094SBarry Smith 
2252dc4c0fb0SBarry 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
2253f6dfbefdSBarry Smith     A(x^{n}) is used to build the preconditioner
22546b7fb656SBarry Smith 
2255dc4c0fb0SBarry 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.
22566b7fb656SBarry Smith 
2257dc4c0fb0SBarry 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
22586b7fb656SBarry 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
2259f6dfbefdSBarry 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`.
2260*aaa8cc7dSPierre Jolivet    See the comment in src/snes/tutorials/ex15.c.
2261bbc1464cSBarry Smith 
2262dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, `SNESJacobianFunction`
22638b0a5094SBarry Smith @*/
2264d71ae5a4SJacob 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)
2265d71ae5a4SJacob Faibussowitsch {
2266e03ab78fSPeter Brune   DM dm;
2267e03ab78fSPeter Brune 
22688b0a5094SBarry Smith   PetscFunctionBegin;
22698b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22709566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22719566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22729566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22739566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22749566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22768b0a5094SBarry Smith }
22778b0a5094SBarry Smith 
22787971a8bfSPeter Brune /*@C
22797971a8bfSPeter Brune    SNESGetPicard - Returns the context for the Picard iteration
22807971a8bfSPeter Brune 
2281f6dfbefdSBarry Smith    Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
22827971a8bfSPeter Brune 
22837971a8bfSPeter Brune    Input Parameter:
2284f6dfbefdSBarry Smith .  snes - the `SNES` context
22857971a8bfSPeter Brune 
2286d8d19677SJose E. Roman    Output Parameters:
2287dc4c0fb0SBarry Smith +  r - the function (or `NULL`)
228820f4b53cSBarry Smith .  f - the function (or `NULL`);  for calling sequence see `SNESFunction`
2289dc4c0fb0SBarry Smith .  Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2290dc4c0fb0SBarry Smith .  Pmat  - the matrix from which the preconditioner will be constructed (or `NULL`)
229120f4b53cSBarry Smith .  J - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFunction`
2292dc4c0fb0SBarry Smith -  ctx - the function context (or `NULL`)
22937971a8bfSPeter Brune 
22947971a8bfSPeter Brune    Level: advanced
22957971a8bfSPeter Brune 
2296dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunction`, `SNESJacobianFunction`
22977971a8bfSPeter Brune @*/
2298d71ae5a4SJacob 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)
2299d71ae5a4SJacob Faibussowitsch {
23007971a8bfSPeter Brune   DM dm;
23017971a8bfSPeter Brune 
23027971a8bfSPeter Brune   PetscFunctionBegin;
23037971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23049566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23059566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23069566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23079566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23097971a8bfSPeter Brune }
23107971a8bfSPeter Brune 
2311d25893d9SBarry Smith /*@C
2312dc4c0fb0SBarry Smith    SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2313d25893d9SBarry Smith 
2314c3339decSBarry Smith    Logically Collective
2315d25893d9SBarry Smith 
2316d25893d9SBarry Smith    Input Parameters:
2317f6dfbefdSBarry Smith +  snes - the `SNES` context
2318d25893d9SBarry Smith .  func - function evaluation routine
2319d25893d9SBarry Smith -  ctx - [optional] user-defined context for private data for the
2320dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2321d25893d9SBarry Smith 
232220f4b53cSBarry Smith    Calling sequence of `func`:
232320f4b53cSBarry Smith $    PetscErrorCode func(SNES snes, Vec x, void *ctx);
232420f4b53cSBarry Smith +  snes - the `SNES` solver
232520f4b53cSBarry Smith .  x - vector to put initial guess
2326d25893d9SBarry Smith -  ctx - optional user-defined function context
2327d25893d9SBarry Smith 
2328d25893d9SBarry Smith    Level: intermediate
2329d25893d9SBarry Smith 
2330dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`
2331d25893d9SBarry Smith @*/
2332d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetComputeInitialGuess(SNES snes, PetscErrorCode (*func)(SNES, Vec, void *), void *ctx)
2333d71ae5a4SJacob Faibussowitsch {
2334d25893d9SBarry Smith   PetscFunctionBegin;
2335d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2336d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2337d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2339d25893d9SBarry Smith }
2340d25893d9SBarry Smith 
23411096aae1SMatthew Knepley /*@C
2342dc4c0fb0SBarry Smith    SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
23431096aae1SMatthew Knepley    it assumes a zero right hand side.
23441096aae1SMatthew Knepley 
2345c3339decSBarry Smith    Logically Collective
23461096aae1SMatthew Knepley 
23471096aae1SMatthew Knepley    Input Parameter:
2348f6dfbefdSBarry Smith .  snes - the `SNES` context
23491096aae1SMatthew Knepley 
23501096aae1SMatthew Knepley    Output Parameter:
2351dc4c0fb0SBarry Smith .  rhs - the right hand side vector or `NULL` if the right hand side vector is null
23521096aae1SMatthew Knepley 
23531096aae1SMatthew Knepley    Level: intermediate
23541096aae1SMatthew Knepley 
2355dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23561096aae1SMatthew Knepley @*/
2357d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2358d71ae5a4SJacob Faibussowitsch {
23591096aae1SMatthew Knepley   PetscFunctionBegin;
23600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23611096aae1SMatthew Knepley   PetscValidPointer(rhs, 2);
236285385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23641096aae1SMatthew Knepley }
23651096aae1SMatthew Knepley 
23669b94acceSBarry Smith /*@
2367f6dfbefdSBarry Smith    SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23689b94acceSBarry Smith 
2369c3339decSBarry Smith    Collective
2370c7afd0dbSLois Curfman McInnes 
23719b94acceSBarry Smith    Input Parameters:
2372f6dfbefdSBarry Smith +  snes - the `SNES` context
2373c7afd0dbSLois Curfman McInnes -  x - input vector
23749b94acceSBarry Smith 
23759b94acceSBarry Smith    Output Parameter:
2376f6dfbefdSBarry Smith .  y - function vector, as set by `SNESSetFunction()`
23779b94acceSBarry Smith 
2378dc4c0fb0SBarry Smith    Level: developer
2379dc4c0fb0SBarry Smith 
2380f6dfbefdSBarry Smith    Note:
2381f6dfbefdSBarry Smith    `SNESComputeFunction()` is typically used within nonlinear solvers
2382bbc1464cSBarry Smith    implementations, so users would not generally call this routine themselves.
238336851e7fSLois Curfman McInnes 
2384dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
23859b94acceSBarry Smith @*/
2386d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2387d71ae5a4SJacob Faibussowitsch {
23886cab3a1bSJed Brown   DM     dm;
2389942e3340SBarry Smith   DMSNES sdm;
23909b94acceSBarry Smith 
23913a40ed3dSBarry Smith   PetscFunctionBegin;
23920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23930700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
23940700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2395c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2396c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2397e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2398184914b5SBarry Smith 
23999566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24009566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24010fdf79fbSJacob 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().");
240232f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
240348a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24049566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24058ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24068ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2407800f99ffSJeremy L Thompson     {
2408800f99ffSJeremy L Thompson       void *ctx;
2409800f99ffSJeremy L Thompson       PetscErrorCode (*computefunction)(SNES, Vec, Vec, void *);
2410800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2411800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2412800f99ffSJeremy L Thompson     }
24139566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
241448a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24150fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24169566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24170fdf79fbSJacob Faibussowitsch   }
24181baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2419ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2420422a814eSBarry Smith   /*
2421422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2422422a814eSBarry Smith      propagate the value to all processes
2423422a814eSBarry Smith   */
24241baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24269b94acceSBarry Smith }
24279b94acceSBarry Smith 
2428c79ef259SPeter Brune /*@
2429f6dfbefdSBarry Smith    SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2430bbc1464cSBarry Smith 
2431c3339decSBarry Smith    Collective
2432bbc1464cSBarry Smith 
2433bbc1464cSBarry Smith    Input Parameters:
2434f6dfbefdSBarry Smith +  snes - the `SNES` context
2435bbc1464cSBarry Smith -  x - input vector
2436bbc1464cSBarry Smith 
2437bbc1464cSBarry Smith    Output Parameter:
2438f6dfbefdSBarry Smith .  y - function vector, as set by `SNESSetMFFunction()`
2439bbc1464cSBarry Smith 
2440dc4c0fb0SBarry Smith    Level: developer
2441dc4c0fb0SBarry Smith 
2442bbc1464cSBarry Smith    Notes:
2443f6dfbefdSBarry Smith    `SNESComputeMFFunction()` is used within the matrix vector products called by the matrix created with `MatCreateSNESMF()`
2444bbc1464cSBarry Smith    so users would not generally call this routine themselves.
2445bbc1464cSBarry Smith 
2446f6dfbefdSBarry Smith     Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with `SNESSolve()`
2447f6dfbefdSBarry Smith     while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2448f6dfbefdSBarry 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.
2449bbc1464cSBarry Smith 
2450dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2451bbc1464cSBarry Smith @*/
2452d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2453d71ae5a4SJacob Faibussowitsch {
2454bbc1464cSBarry Smith   DM     dm;
2455bbc1464cSBarry Smith   DMSNES sdm;
2456bbc1464cSBarry Smith 
2457bbc1464cSBarry Smith   PetscFunctionBegin;
2458bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2459bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2460bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2461bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2462bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2463e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2464bbc1464cSBarry Smith 
24659566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24669566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24689566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2469bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2470bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2471792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24729566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2474bbc1464cSBarry Smith   snes->nfuncs++;
2475bbc1464cSBarry Smith   /*
2476bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2477bbc1464cSBarry Smith      propagate the value to all processes
2478bbc1464cSBarry Smith   */
24791baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2481bbc1464cSBarry Smith }
2482bbc1464cSBarry Smith 
2483bbc1464cSBarry Smith /*@
2484f6dfbefdSBarry Smith    SNESComputeNGS - Calls the Gauss-Seidel function that has been set with  `SNESSetNGS()`.
2485c79ef259SPeter Brune 
2486c3339decSBarry Smith    Collective
2487c79ef259SPeter Brune 
2488c79ef259SPeter Brune    Input Parameters:
2489f6dfbefdSBarry Smith +  snes - the `SNES` context
2490c79ef259SPeter Brune .  x - input vector
2491c79ef259SPeter Brune -  b - rhs vector
2492c79ef259SPeter Brune 
2493c79ef259SPeter Brune    Output Parameter:
2494c79ef259SPeter Brune .  x - new solution vector
2495c79ef259SPeter Brune 
2496dc4c0fb0SBarry Smith    Level: developer
2497dc4c0fb0SBarry Smith 
2498f6dfbefdSBarry Smith    Note:
2499f6dfbefdSBarry Smith    `SNESComputeNGS()` is typically used within composed nonlinear solver
2500c79ef259SPeter Brune    implementations, so most users would not generally call this routine
2501c79ef259SPeter Brune    themselves.
2502c79ef259SPeter Brune 
2503dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESNGS`, `SNESSetNGS()`, `SNESComputeFunction()`
2504c79ef259SPeter Brune @*/
2505d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2506d71ae5a4SJacob Faibussowitsch {
25076cab3a1bSJed Brown   DM     dm;
2508942e3340SBarry Smith   DMSNES sdm;
2509646217ecSPeter Brune 
2510646217ecSPeter Brune   PetscFunctionBegin;
2511646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2512064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2513064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2514064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2515064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2516e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25189566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25199566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25200fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25219566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2522792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25239566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2526646217ecSPeter Brune }
2527646217ecSPeter Brune 
2528d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2529d71ae5a4SJacob Faibussowitsch {
253012837594SBarry Smith   Mat               A, B, C, D, jacobian;
2531e885f1abSBarry Smith   Vec               x = snes->vec_sol, f = snes->vec_func;
2532e885f1abSBarry Smith   PetscReal         nrm, gnorm;
253381e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
25340e276705SLisandro Dalcin   MatType           mattype;
2535e885f1abSBarry Smith   PetscInt          m, n, M, N;
2536e885f1abSBarry Smith   void             *functx;
25372cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
25383325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2539e885f1abSBarry Smith   MPI_Comm          comm;
2540e885f1abSBarry Smith   PetscInt          tabs;
254112837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
25423325ff46SBarry Smith   PetscViewerFormat format;
2543e885f1abSBarry Smith 
2544e885f1abSBarry Smith   PetscFunctionBegin;
2545d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
25469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
25479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
25489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
254918d89885SKarl Rupp   if (!complete_print) {
25509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
25519566063dSJacob Faibussowitsch     PetscCall(PetscOptionsViewer("-snes_test_jacobian_display", "Display difference between hand-coded and finite difference Jacobians", "None", &mviewer, &format, &complete_print));
255218d89885SKarl Rupp   }
255318d89885SKarl Rupp   /* for compatibility with PETSc 3.9 and older. */
25549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
25559566063dSJacob 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));
2556d0609cedSBarry Smith   PetscOptionsEnd();
25573ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2558e885f1abSBarry Smith 
25599566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
25609566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
25619566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
25629566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
25639566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
256412837594SBarry Smith   if (!complete_print && !directionsprinted) {
25659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
25669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
256712837594SBarry Smith   }
256812837594SBarry Smith   if (!directionsprinted) {
25699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
25709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
257112837594SBarry Smith     directionsprinted = PETSC_TRUE;
2572e885f1abSBarry Smith   }
25731baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2574e885f1abSBarry Smith 
25759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
257612837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
257712837594SBarry Smith   else jacobian = snes->jacobian_pre;
257812837594SBarry Smith 
2579a82339d0SMatthew G. Knepley   if (!x) {
25809566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(jacobian, &x, NULL));
2581a82339d0SMatthew G. Knepley   } else {
25829566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
2583a82339d0SMatthew G. Knepley   }
2584a82339d0SMatthew G. Knepley   if (!f) {
25859566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &f));
2586a82339d0SMatthew G. Knepley   } else {
25879566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)f));
2588a82339d0SMatthew G. Knepley   }
2589a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
25909566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
25919566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
25929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
259312837594SBarry Smith   while (jacobian) {
25942cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
25952cd624f9SStefano Zampini 
25962cd624f9SStefano Zampini     if (istranspose) {
25979566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
25982cd624f9SStefano Zampini       Jsave    = jacobian;
25992cd624f9SStefano Zampini       jacobian = JT;
26002cd624f9SStefano Zampini     }
26019566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
260212837594SBarry Smith     if (flg) {
260312837594SBarry Smith       A = jacobian;
26049566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
260512837594SBarry Smith     } else {
26069566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
260712837594SBarry Smith     }
2608e885f1abSBarry Smith 
26099566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
26109566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
26119566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
26129566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
26139566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
26149566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
26159566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
26169566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
26179566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2618e885f1abSBarry Smith 
26199566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
26209566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
262112837594SBarry Smith 
26229566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
26239566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26249566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
26259566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
26269566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
262712837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
26289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
262912837594SBarry Smith 
2630e885f1abSBarry Smith     if (complete_print) {
26319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
26329566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
26339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
26349566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2635e885f1abSBarry Smith     }
2636e885f1abSBarry Smith 
2637df10fb39SFande Kong     if (threshold_print || complete_print) {
2638e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2639e885f1abSBarry Smith       PetscScalar       *cvals;
2640e885f1abSBarry Smith       const PetscInt    *bcols;
2641e885f1abSBarry Smith       const PetscScalar *bvals;
2642e885f1abSBarry Smith 
26439566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
26449566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
26459566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
26469566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
26479566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
26489566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
26490e276705SLisandro Dalcin 
26509566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26519566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2652e885f1abSBarry Smith 
2653e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
26549566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
26559566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2656e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
265723a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2658e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2659e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2660e885f1abSBarry Smith             cncols += 1;
2661e885f1abSBarry Smith           }
2662e885f1abSBarry Smith         }
266348a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
26649566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
26659566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2666e885f1abSBarry Smith       }
26679566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
26689566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
26699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
26709566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
26719566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2672e885f1abSBarry Smith     }
26739566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
26749566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
26759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
26762cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
267712837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
267812837594SBarry Smith       jacobian = snes->jacobian_pre;
26799566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
26809371c9d4SSatish Balay     } else jacobian = NULL;
268112837594SBarry Smith   }
26829566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
26831baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
26849566063dSJacob Faibussowitsch   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
26859566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
26863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2687e885f1abSBarry Smith }
2688e885f1abSBarry Smith 
268962fef451SLois Curfman McInnes /*@
2690f6dfbefdSBarry Smith    SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
269162fef451SLois Curfman McInnes 
2692c3339decSBarry Smith    Collective
2693c7afd0dbSLois Curfman McInnes 
269462fef451SLois Curfman McInnes    Input Parameters:
2695f6dfbefdSBarry Smith +  snes - the `SNES` context
2696c7afd0dbSLois Curfman McInnes -  x - input vector
269762fef451SLois Curfman McInnes 
269862fef451SLois Curfman McInnes    Output Parameters:
2699c7afd0dbSLois Curfman McInnes +  A - Jacobian matrix
2700f6dfbefdSBarry Smith -  B - optional matrix for building the preconditioner
2701fee21e36SBarry Smith 
2702e35cf81dSBarry Smith   Options Database Keys:
270367b8a455SSatish Balay +    -snes_lag_preconditioner <lag> - how often to rebuild preconditioner
270467b8a455SSatish Balay .    -snes_lag_jacobian <lag> - how often to rebuild Jacobian
2705455a5933SJed 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.
2706455a5933SJed 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
2707693365a8SJed Brown .    -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2708693365a8SJed Brown .    -snes_compare_explicit_draw  - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2709693365a8SJed Brown .    -snes_compare_explicit_contour  - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
27104c30e9fbSJed Brown .    -snes_compare_operator  - Make the comparison options above use the operator instead of the preconditioning matrix
271194d6a431SBarry Smith .    -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference
2712a5b23f4aSJose E. Roman .    -snes_compare_coloring_display - Compute the finite difference Jacobian using coloring and display verbose differences
2713c01495d3SJed Brown .    -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold
2714dc4c0fb0SBarry Smith .    -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2715dc4c0fb0SBarry Smith .    -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2716a5b23f4aSJose E. Roman .    -snes_compare_coloring_draw - Compute the finite difference Jacobian using coloring and draw differences
2717a5b23f4aSJose E. Roman -    -snes_compare_coloring_draw_contour - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2718c01495d3SJed Brown 
2719dc4c0fb0SBarry Smith    Level: developer
2720dc4c0fb0SBarry Smith 
2721f6dfbefdSBarry Smith    Note:
272262fef451SLois Curfman McInnes    Most users should not need to explicitly call this routine, as it
272362fef451SLois Curfman McInnes    is used internally within the nonlinear solvers.
272462fef451SLois Curfman McInnes 
2725f6dfbefdSBarry Smith    Developer Note:
2726dc4c0fb0SBarry 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
2727dc4c0fb0SBarry Smith       for with the `SNESType` of test that has been removed.
2728e885f1abSBarry Smith 
2729dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
273062fef451SLois Curfman McInnes @*/
2731d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2732d71ae5a4SJacob Faibussowitsch {
2733ace3abfcSBarry Smith   PetscBool flag;
27346cab3a1bSJed Brown   DM        dm;
2735942e3340SBarry Smith   DMSNES    sdm;
2736e0e3a89bSBarry Smith   KSP       ksp;
27373a40ed3dSBarry Smith 
27383a40ed3dSBarry Smith   PetscFunctionBegin;
27390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
27400700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2741c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2742e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
27439566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
27449566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
27453232da50SPeter Brune 
2746ebd3b9afSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */
2747fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2748fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2749f5af7f23SKarl Rupp 
27509566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2751fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
27529566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
27539566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2754ebd3b9afSBarry Smith     if (flag) {
27559566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27569566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2757ebd3b9afSBarry Smith     }
27583ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
275937ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
276063a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
27619566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2762ebd3b9afSBarry Smith     if (flag) {
27639566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27649566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2765ebd3b9afSBarry Smith     }
27663ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2767e35cf81dSBarry Smith   }
2768efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
27699566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27709566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
27713ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2772d728fb7dSPeter Brune   }
2773e35cf81dSBarry Smith 
27749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
27759566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2776800f99ffSJeremy L Thompson   {
2777800f99ffSJeremy L Thompson     void *ctx;
2778800f99ffSJeremy L Thompson     PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *);
2779800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2780800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2781800f99ffSJeremy L Thompson   }
27829566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
27839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
278428d58a37SPierre Jolivet 
278528d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
27869566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2787a8054027SBarry Smith 
2788e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
27899566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
27903b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
27919566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
27929566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
27933b4f5425SBarry Smith     snes->lagpreconditioner = -1;
27943b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
27959566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
27969566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
279737ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
279863a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
27999566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2800d1e9a80fSBarry Smith   } else {
28019566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
28029566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2803a8054027SBarry Smith   }
2804a8054027SBarry Smith 
28059566063dSJacob Faibussowitsch   PetscCall(SNESTestJacobian(snes));
28066d84be18SBarry Smith   /* make sure user returned a correct Jacobian and preconditioner */
280794ab13aaSBarry Smith   /* PetscValidHeaderSpecific(A,MAT_CLASSID,3);
280894ab13aaSBarry Smith     PetscValidHeaderSpecific(B,MAT_CLASSID,4);   */
2809693365a8SJed Brown   {
2810693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
28119566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
28129566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
28139566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
28149566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2815693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
28160298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2817693365a8SJed Brown       PetscViewer vdraw, vstdout;
28186b3a5b13SJed Brown       PetscBool   flg;
2819693365a8SJed Brown       if (flag_operator) {
28209566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2821693365a8SJed Brown         Bexp = Bexp_mine;
2822693365a8SJed Brown       } else {
2823693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
28249566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
282594ab13aaSBarry Smith         if (flg) Bexp = B;
2826693365a8SJed Brown         else {
2827693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
28289566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2829693365a8SJed Brown           Bexp = Bexp_mine;
2830693365a8SJed Brown         }
2831693365a8SJed Brown       }
28329566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
28339566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
28349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2835693365a8SJed Brown       if (flag_draw || flag_contour) {
28369566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28379566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28380298fd71SBarry Smith       } else vdraw = NULL;
28399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
28409566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
28419566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
28429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
28439566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
28449566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
28459566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
28469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
28479566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2848693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
28499566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28509566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
28519566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2852693365a8SJed Brown       }
28539566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
28549566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
28559566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
28569566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2857693365a8SJed Brown     }
2858693365a8SJed Brown   }
28594c30e9fbSJed Brown   {
28606719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
28616719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
28629566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
28639566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
28649566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
28659566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
28669566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
286727b0f280SBarry Smith     if (flag_threshold) {
28689566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
28699566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
287027b0f280SBarry Smith     }
28716719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
28724c30e9fbSJed Brown       Mat           Bfd;
28734c30e9fbSJed Brown       PetscViewer   vdraw, vstdout;
2874335efc43SPeter Brune       MatColoring   coloring;
28754c30e9fbSJed Brown       ISColoring    iscoloring;
28764c30e9fbSJed Brown       MatFDColoring matfdcoloring;
28774c30e9fbSJed Brown       PetscErrorCode (*func)(SNES, Vec, Vec, void *);
28784c30e9fbSJed Brown       void     *funcctx;
28796719d8e4SJed Brown       PetscReal norm1, norm2, normmax;
28804c30e9fbSJed Brown 
28819566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
28829566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
28839566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
28849566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
28859566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
28869566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
28879566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
28889566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28899566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
28909566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
28914c30e9fbSJed Brown 
28924c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
28939566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
28949566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
28959566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
28969566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
28979566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28989566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
28999566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
29004c30e9fbSJed Brown 
29019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
29024c30e9fbSJed Brown       if (flag_draw || flag_contour) {
29039566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
29049566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29050298fd71SBarry Smith       } else vdraw = NULL;
29069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
29079566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
29089566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
29099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
29109566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29119566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
29129566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
29139566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
29149566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
29159566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
29169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
29179566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29184c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
29199566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29209566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
29219566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
29224c30e9fbSJed Brown       }
29239566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29246719d8e4SJed Brown 
29256719d8e4SJed Brown       if (flag_threshold) {
29266719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
29279566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
29289566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
29296719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
29306719d8e4SJed Brown           const PetscScalar *ba, *ca;
29316719d8e4SJed Brown           const PetscInt    *bj, *cj;
29326719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
29336719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
29349566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
29359566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
29365f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
29376719d8e4SJed Brown           for (j = 0; j < bn; j++) {
29386719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
29396719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
29406719d8e4SJed Brown               maxentrycol = bj[j];
29416719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
29426719d8e4SJed Brown             }
29436719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
29446719d8e4SJed Brown               maxdiffcol = bj[j];
29456719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
29466719d8e4SJed Brown             }
29476719d8e4SJed Brown             if (rdiff > maxrdiff) {
29486719d8e4SJed Brown               maxrdiffcol = bj[j];
29496719d8e4SJed Brown               maxrdiff    = rdiff;
29506719d8e4SJed Brown             }
29516719d8e4SJed Brown           }
29526719d8e4SJed Brown           if (maxrdiff > 1) {
295363a3b9bcSJacob 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));
29546719d8e4SJed Brown             for (j = 0; j < bn; j++) {
29556719d8e4SJed Brown               PetscReal rdiff;
29566719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
295748a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
29586719d8e4SJed Brown             }
295963a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
29606719d8e4SJed Brown           }
29619566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
29629566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
29636719d8e4SJed Brown         }
29646719d8e4SJed Brown       }
29659566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
29674c30e9fbSJed Brown     }
29684c30e9fbSJed Brown   }
29693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29709b94acceSBarry Smith }
29719b94acceSBarry Smith 
2972bf388a1fSBarry Smith /*MC
2973f6dfbefdSBarry Smith     SNESJacobianFunction - Function used by `SNES` to compute the nonlinear Jacobian of the function to be solved by `SNES`
2974bf388a1fSBarry Smith 
2975bf388a1fSBarry Smith      Synopsis:
2976411c0326SBarry Smith      #include "petscsnes.h"
2977411c0326SBarry Smith      PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
2978bf388a1fSBarry Smith 
2979c3339decSBarry Smith      Collective
29801843f636SBarry Smith 
29811843f636SBarry Smith     Input Parameters:
29821843f636SBarry Smith +  x - input vector, the Jacobian is to be computed at this value
2983bf388a1fSBarry Smith -  ctx - [optional] user-defined Jacobian context
2984bf388a1fSBarry Smith 
29851843f636SBarry Smith     Output Parameters:
29861843f636SBarry Smith +  Amat - the matrix that defines the (approximate) Jacobian
2987dc4c0fb0SBarry Smith -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
29881843f636SBarry Smith 
2989878cb397SSatish Balay    Level: intermediate
2990878cb397SSatish Balay 
2991dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESSetJacobian()`, `SNESGetJacobian()`
2992bf388a1fSBarry Smith M*/
2993bf388a1fSBarry Smith 
29949b94acceSBarry Smith /*@C
29959b94acceSBarry Smith    SNESSetJacobian - Sets the function to compute Jacobian as well as the
2996044dda88SLois Curfman McInnes    location to store the matrix.
29979b94acceSBarry Smith 
2998c3339decSBarry Smith    Logically Collective
2999c7afd0dbSLois Curfman McInnes 
30009b94acceSBarry Smith    Input Parameters:
3001f6dfbefdSBarry Smith +  snes - the `SNES` context
3002e5d3d808SBarry Smith .  Amat - the matrix that defines the (approximate) Jacobian
3003dc4c0fb0SBarry Smith .  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
3004dc4c0fb0SBarry Smith .  J - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFunction` for details
3005c7afd0dbSLois Curfman McInnes -  ctx - [optional] user-defined context for private data for the
3006dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3007dc4c0fb0SBarry Smith 
3008dc4c0fb0SBarry Smith    Level: beginner
30099b94acceSBarry Smith 
30109b94acceSBarry Smith    Notes:
3011dc4c0fb0SBarry Smith    If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
301216913363SBarry Smith    each matrix.
301316913363SBarry Smith 
3014dc4c0fb0SBarry Smith    If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3015dc4c0fb0SBarry Smith    space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3016895c21f2SBarry Smith 
3017dc4c0fb0SBarry Smith    If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3018f6dfbefdSBarry Smith    must be a `MatFDColoring`.
3019a8a26c1eSJed Brown 
3020c3cc8fd1SJed Brown    Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3021f6dfbefdSBarry Smith    example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3022c3cc8fd1SJed Brown 
3023dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
3024db781477SPatrick Sanan           `SNESSetPicard()`, `SNESJacobianFunction`
30259b94acceSBarry Smith @*/
3026d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx)
3027d71ae5a4SJacob Faibussowitsch {
30286cab3a1bSJed Brown   DM dm;
30293a7fca6bSBarry Smith 
30303a40ed3dSBarry Smith   PetscFunctionBegin;
30310700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3032e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3033e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3034e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3035e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
30369566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30379566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3038e5d3d808SBarry Smith   if (Amat) {
30399566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
30409566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3041f5af7f23SKarl Rupp 
3042e5d3d808SBarry Smith     snes->jacobian = Amat;
30433a7fca6bSBarry Smith   }
3044e5d3d808SBarry Smith   if (Pmat) {
30459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
30469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3047f5af7f23SKarl Rupp 
3048e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
30493a7fca6bSBarry Smith   }
30503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30519b94acceSBarry Smith }
305262fef451SLois Curfman McInnes 
3053c2aafc4cSSatish Balay /*@C
3054b4fd4287SBarry Smith    SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3055b4fd4287SBarry Smith    provided context for evaluating the Jacobian.
3056b4fd4287SBarry Smith 
3057f6dfbefdSBarry Smith    Not Collective, but `Mat` object will be parallel if `SNES` object is
3058c7afd0dbSLois Curfman McInnes 
3059b4fd4287SBarry Smith    Input Parameter:
3060b4fd4287SBarry Smith .  snes - the nonlinear solver context
3061b4fd4287SBarry Smith 
3062b4fd4287SBarry Smith    Output Parameters:
3063dc4c0fb0SBarry Smith +  Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3064dc4c0fb0SBarry Smith .  Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
306520f4b53cSBarry Smith .  J - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFunction`
3066dc4c0fb0SBarry Smith -  ctx - location to stash Jacobian ctx (or `NULL`)
3067fee21e36SBarry Smith 
306836851e7fSLois Curfman McInnes    Level: advanced
306936851e7fSLois Curfman McInnes 
3070dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFunction`, `SNESGetFunction()`
3071b4fd4287SBarry Smith @*/
3072d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx)
3073d71ae5a4SJacob Faibussowitsch {
30746cab3a1bSJed Brown   DM dm;
30756cab3a1bSJed Brown 
30763a40ed3dSBarry Smith   PetscFunctionBegin;
30770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3078e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3079e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
30809566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3081800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
30823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3083b4fd4287SBarry Smith }
3084b4fd4287SBarry Smith 
3085d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3086d71ae5a4SJacob Faibussowitsch {
308758b371f3SBarry Smith   DM     dm;
308858b371f3SBarry Smith   DMSNES sdm;
308958b371f3SBarry Smith 
309058b371f3SBarry Smith   PetscFunctionBegin;
30919566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30929566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
309358b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
309458b371f3SBarry Smith     DM        dm;
309558b371f3SBarry Smith     PetscBool isdense, ismf;
309658b371f3SBarry Smith 
30979566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
30989566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
30999566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
310058b371f3SBarry Smith     if (isdense) {
31019566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
310258b371f3SBarry Smith     } else if (!ismf) {
31039566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
310458b371f3SBarry Smith     }
310558b371f3SBarry Smith   }
31063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
310758b371f3SBarry Smith }
310858b371f3SBarry Smith 
31099b94acceSBarry Smith /*@
31109b94acceSBarry Smith    SNESSetUp - Sets up the internal data structures for the later use
3111272ac6f2SLois Curfman McInnes    of a nonlinear solver.
31129b94acceSBarry Smith 
3113c3339decSBarry Smith    Collective
3114fee21e36SBarry Smith 
31152fe279fdSBarry Smith    Input Parameter:
3116f6dfbefdSBarry Smith .  snes - the `SNES` context
3117c7afd0dbSLois Curfman McInnes 
3118dc4c0fb0SBarry Smith    Level: advanced
3119dc4c0fb0SBarry Smith 
3120f6dfbefdSBarry Smith    Note:
3121f6dfbefdSBarry Smith    For basic use of the `SNES` solvers the user need not explicitly call
3122f6dfbefdSBarry Smith    `SNESSetUp()`, since these actions will automatically occur during
3123f6dfbefdSBarry Smith    the call to `SNESSolve()`.  However, if one wishes to control this
3124f6dfbefdSBarry Smith    phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3125f6dfbefdSBarry Smith    and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3126272ac6f2SLois Curfman McInnes 
3127dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
31289b94acceSBarry Smith @*/
3129d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3130d71ae5a4SJacob Faibussowitsch {
31316cab3a1bSJed Brown   DM             dm;
3132942e3340SBarry Smith   DMSNES         sdm;
3133c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
31346e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
31359b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
31369b5c1c08SStefano Zampini   Vec            f, fpc;
31379b5c1c08SStefano Zampini   void          *funcctx;
31389b5c1c08SStefano Zampini   void          *jacctx, *appctx;
31399b5c1c08SStefano Zampini   Mat            j, jpre;
31406b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
31416b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
31426e2a1849SPeter Brune   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
3143d1e9a80fSBarry Smith   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
31443a40ed3dSBarry Smith 
31453a40ed3dSBarry Smith   PetscFunctionBegin;
31460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31473ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3148fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
31499b94acceSBarry Smith 
315048a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
315185385478SLisandro Dalcin 
31529566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
315358c9b817SLisandro Dalcin 
31549566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31559566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
31569566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
315758b371f3SBarry Smith 
315848a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3159efd51863SBarry Smith 
316048a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3161b710008aSBarry Smith 
3162d8d34be6SBarry Smith   if (snes->linesearch) {
31639566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
31649566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3165d8d34be6SBarry Smith   }
31669e764e56SPeter Brune 
31679b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3168b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3169172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3170172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3171172a4300SPeter Brune   }
3172d8f46077SPeter Brune 
3173efd4aadfSBarry Smith   if (snes->npc) {
31746e2a1849SPeter Brune     /* copy the DM over */
31759566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31769566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
31776e2a1849SPeter Brune 
31789566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
31799566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
31809566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
31819566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
31829566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
31839566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
31849566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
31859b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
31869566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
31876e2a1849SPeter Brune 
31886e2a1849SPeter Brune     /* copy the function pointers over */
31899566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
31906e2a1849SPeter Brune 
31916e2a1849SPeter Brune     /* default to 1 iteration */
31929566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3193efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
31949566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3195a9936a0cSPeter Brune     } else {
31969566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3197a9936a0cSPeter Brune     }
31989566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
31996e2a1849SPeter Brune 
32006e2a1849SPeter Brune     /* copy the line search context over */
3201d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
32029566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
32039566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
32049566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
32059566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
32069566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
32079566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
32089566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
32096e2a1849SPeter Brune     }
3210d8d34be6SBarry Smith   }
32111baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
321248a46eb9SPierre Jolivet   if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user));
32136e2a1849SPeter Brune 
321437ec4e1aSPeter Brune   snes->jac_iter = 0;
321537ec4e1aSPeter Brune   snes->pre_iter = 0;
321637ec4e1aSPeter Brune 
3217dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
321858c9b817SLisandro Dalcin 
32199566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
322058b371f3SBarry Smith 
3221b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
32226c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3223d8d34be6SBarry Smith       if (snes->linesearch) {
32249566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
32259566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
32266c67d002SPeter Brune       }
32276c67d002SPeter Brune     }
3228d8d34be6SBarry Smith   }
3229fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
32307aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
32313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32329b94acceSBarry Smith }
32339b94acceSBarry Smith 
323437596af1SLisandro Dalcin /*@
3235f6dfbefdSBarry Smith    SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
323637596af1SLisandro Dalcin 
3237c3339decSBarry Smith    Collective
323837596af1SLisandro Dalcin 
323937596af1SLisandro Dalcin    Input Parameter:
3240f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
324137596af1SLisandro Dalcin 
3242d25893d9SBarry Smith    Level: intermediate
3243d25893d9SBarry Smith 
324495452b02SPatrick Sanan    Notes:
3245f6dfbefdSBarry Smith    Call this if you wish to reuse a `SNES` but with different size vectors
324637596af1SLisandro Dalcin 
3247f6dfbefdSBarry Smith    Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3248f6dfbefdSBarry Smith 
3249dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
325037596af1SLisandro Dalcin @*/
3251d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3252d71ae5a4SJacob Faibussowitsch {
325337596af1SLisandro Dalcin   PetscFunctionBegin;
325437596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3255d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
32569566063dSJacob Faibussowitsch     PetscCall((*snes->ops->userdestroy)((void **)&snes->user));
32570298fd71SBarry Smith     snes->user = NULL;
3258d25893d9SBarry Smith   }
32591baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
32608a23116dSBarry Smith 
3261dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
32621baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
32639e764e56SPeter Brune 
32641baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
32659e764e56SPeter Brune 
32669566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
32679566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
32689566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
32699566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
32709566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
32719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
32729566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
32739566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
32749566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3275f5af7f23SKarl Rupp 
327640fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
327740fdac6aSLawrence Mitchell 
327837596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
327937596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
32803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
328137596af1SLisandro Dalcin }
328237596af1SLisandro Dalcin 
328352baeb72SSatish Balay /*@
3284f6dfbefdSBarry Smith    SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object.
3285c4421ceaSFande Kong 
3286c3339decSBarry Smith    Collective
3287c4421ceaSFande Kong 
3288c4421ceaSFande Kong    Input Parameter:
3289f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
3290c4421ceaSFande Kong 
3291c4421ceaSFande Kong    Level: intermediate
3292c4421ceaSFande Kong 
3293dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`
3294c4421ceaSFande Kong @*/
3295d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3296d71ae5a4SJacob Faibussowitsch {
3297c4421ceaSFande Kong   PetscInt i;
3298c4421ceaSFande Kong 
3299c4421ceaSFande Kong   PetscFunctionBegin;
3300c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3301c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
330248a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3303c4421ceaSFande Kong   }
3304c4421ceaSFande Kong   snes->numberreasonviews = 0;
33053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3306c4421ceaSFande Kong }
3307c4421ceaSFande Kong 
33081fb7b255SJunchao Zhang /*@C
33099b94acceSBarry Smith    SNESDestroy - Destroys the nonlinear solver context that was created
3310f6dfbefdSBarry Smith    with `SNESCreate()`.
33119b94acceSBarry Smith 
3312c3339decSBarry Smith    Collective
3313c7afd0dbSLois Curfman McInnes 
33149b94acceSBarry Smith    Input Parameter:
3315f6dfbefdSBarry Smith .  snes - the `SNES` context
33169b94acceSBarry Smith 
331736851e7fSLois Curfman McInnes    Level: beginner
331836851e7fSLois Curfman McInnes 
3319dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
33209b94acceSBarry Smith @*/
3321d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3322d71ae5a4SJacob Faibussowitsch {
33233a40ed3dSBarry Smith   PetscFunctionBegin;
33243ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
33256bf464f9SBarry Smith   PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1);
33269371c9d4SSatish Balay   if (--((PetscObject)(*snes))->refct > 0) {
33279371c9d4SSatish Balay     *snes = NULL;
33283ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
33299371c9d4SSatish Balay   }
3330d4bb536fSBarry Smith 
33319566063dSJacob Faibussowitsch   PetscCall(SNESReset((*snes)));
33329566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
33336b8b9a38SLisandro Dalcin 
3334e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
33359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3336dbbe0bcdSBarry Smith   PetscTryTypeMethod((*snes), destroy);
33376d4c513bSLisandro Dalcin 
33389566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
33399566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
33409566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
33419566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
33426b8b9a38SLisandro Dalcin 
33439566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
334448a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
334548a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
33469566063dSJacob Faibussowitsch   PetscCall(SNESMonitorCancel((*snes)));
33479566063dSJacob Faibussowitsch   PetscCall(SNESConvergedReasonViewCancel((*snes)));
33489566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
33493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33509b94acceSBarry Smith }
33519b94acceSBarry Smith 
33529b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
33539b94acceSBarry Smith 
3354a8054027SBarry Smith /*@
3355a8054027SBarry Smith    SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3356a8054027SBarry Smith 
3357c3339decSBarry Smith    Logically Collective
3358a8054027SBarry Smith 
3359a8054027SBarry Smith    Input Parameters:
3360f6dfbefdSBarry Smith +  snes - the `SNES` context
3361d8e291bfSBarry Smith -  lag - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
33623b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3363a8054027SBarry Smith 
3364a8054027SBarry Smith    Options Database Keys:
33653d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
33663d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
33673d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
33683d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3369a8054027SBarry Smith 
3370a8054027SBarry Smith    Notes:
3371dc4c0fb0SBarry Smith    Level: intermediate
3372dc4c0fb0SBarry Smith 
3373a8054027SBarry Smith    The default is 1
3374f6dfbefdSBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3375d8e291bfSBarry Smith 
3376f6dfbefdSBarry Smith    `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3377a8054027SBarry Smith 
3378dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3379f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3380a8054027SBarry Smith @*/
3381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3382d71ae5a4SJacob Faibussowitsch {
3383a8054027SBarry Smith   PetscFunctionBegin;
33840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33855f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
33865f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3387c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3388a8054027SBarry Smith   snes->lagpreconditioner = lag;
33893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3390a8054027SBarry Smith }
3391a8054027SBarry Smith 
3392efd51863SBarry Smith /*@
3393f6dfbefdSBarry Smith    SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3394efd51863SBarry Smith 
3395c3339decSBarry Smith    Logically Collective
3396efd51863SBarry Smith 
3397efd51863SBarry Smith    Input Parameters:
3398f6dfbefdSBarry Smith +  snes - the `SNES` context
3399efd51863SBarry Smith -  steps - the number of refinements to do, defaults to 0
3400efd51863SBarry Smith 
3401f6dfbefdSBarry Smith    Options Database Key:
340267b8a455SSatish Balay .    -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3403efd51863SBarry Smith 
3404efd51863SBarry Smith    Level: intermediate
3405efd51863SBarry Smith 
3406f6dfbefdSBarry Smith    Note:
3407f6dfbefdSBarry Smith    Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3408c0df2a02SJed Brown 
3409dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`
3410efd51863SBarry Smith @*/
3411d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3412d71ae5a4SJacob Faibussowitsch {
3413efd51863SBarry Smith   PetscFunctionBegin;
3414efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3415efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3416efd51863SBarry Smith   snes->gridsequence = steps;
34173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3418efd51863SBarry Smith }
3419efd51863SBarry Smith 
3420fa19ca70SBarry Smith /*@
3421f6dfbefdSBarry Smith    SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3422fa19ca70SBarry Smith 
3423c3339decSBarry Smith    Logically Collective
3424fa19ca70SBarry Smith 
3425fa19ca70SBarry Smith    Input Parameter:
3426f6dfbefdSBarry Smith .  snes - the `SNES` context
3427fa19ca70SBarry Smith 
3428fa19ca70SBarry Smith    Output Parameter:
3429fa19ca70SBarry Smith .  steps - the number of refinements to do, defaults to 0
3430fa19ca70SBarry Smith 
3431f6dfbefdSBarry Smith    Options Database Key:
343267b8a455SSatish Balay .    -snes_grid_sequence <steps> - set number of refinements
3433fa19ca70SBarry Smith 
3434fa19ca70SBarry Smith    Level: intermediate
3435fa19ca70SBarry Smith 
3436f6dfbefdSBarry Smith    Note:
3437f6dfbefdSBarry Smith    Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3438fa19ca70SBarry Smith 
3439dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3440fa19ca70SBarry Smith @*/
3441d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3442d71ae5a4SJacob Faibussowitsch {
3443fa19ca70SBarry Smith   PetscFunctionBegin;
3444fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3445fa19ca70SBarry Smith   *steps = snes->gridsequence;
34463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3447fa19ca70SBarry Smith }
3448fa19ca70SBarry Smith 
3449a8054027SBarry Smith /*@
3450f6dfbefdSBarry Smith    SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3451a8054027SBarry Smith 
34523f9fe445SBarry Smith    Not Collective
3453a8054027SBarry Smith 
3454a8054027SBarry Smith    Input Parameter:
3455f6dfbefdSBarry Smith .  snes - the `SNES` context
3456a8054027SBarry Smith 
3457a8054027SBarry Smith    Output Parameter:
3458a8054027SBarry 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
34593b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3460a8054027SBarry Smith 
3461a8054027SBarry Smith    Options Database Keys:
34623d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
34633d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
34643d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
34653d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
3466a8054027SBarry Smith 
3467dc4c0fb0SBarry Smith    Level: intermediate
3468dc4c0fb0SBarry Smith 
3469a8054027SBarry Smith    Notes:
3470a8054027SBarry Smith    The default is 1
3471f6dfbefdSBarry Smith 
3472a8054027SBarry Smith    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3473a8054027SBarry Smith 
3474dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3475a8054027SBarry Smith @*/
3476d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3477d71ae5a4SJacob Faibussowitsch {
3478a8054027SBarry Smith   PetscFunctionBegin;
34790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3480a8054027SBarry Smith   *lag = snes->lagpreconditioner;
34813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3482a8054027SBarry Smith }
3483a8054027SBarry Smith 
3484e35cf81dSBarry Smith /*@
3485f6dfbefdSBarry Smith    SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3486e35cf81dSBarry Smith      often the preconditioner is rebuilt.
3487e35cf81dSBarry Smith 
3488c3339decSBarry Smith    Logically Collective
3489e35cf81dSBarry Smith 
3490e35cf81dSBarry Smith    Input Parameters:
3491f6dfbefdSBarry Smith +  snes - the `SNES` context
3492e35cf81dSBarry 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
3493fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3494e35cf81dSBarry Smith 
3495e35cf81dSBarry Smith    Options Database Keys:
34963d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
34973d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
34983d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
34993d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag.
3500e35cf81dSBarry Smith 
3501dc4c0fb0SBarry Smith    Level: intermediate
3502dc4c0fb0SBarry Smith 
3503e35cf81dSBarry Smith    Notes:
3504e35cf81dSBarry Smith    The default is 1
3505f6dfbefdSBarry Smith 
3506e35cf81dSBarry Smith    The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3507f6dfbefdSBarry Smith 
3508fe3ffe1eSBarry 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
3509fe3ffe1eSBarry Smith    at the next Newton step but never again (unless it is reset to another value)
3510e35cf81dSBarry Smith 
3511dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3512e35cf81dSBarry Smith @*/
3513d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3514d71ae5a4SJacob Faibussowitsch {
3515e35cf81dSBarry Smith   PetscFunctionBegin;
35160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35175f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35185f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3519c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3520e35cf81dSBarry Smith   snes->lagjacobian = lag;
35213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3522e35cf81dSBarry Smith }
3523e35cf81dSBarry Smith 
3524e35cf81dSBarry Smith /*@
3525f6dfbefdSBarry Smith    SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3526e35cf81dSBarry Smith 
35273f9fe445SBarry Smith    Not Collective
3528e35cf81dSBarry Smith 
3529e35cf81dSBarry Smith    Input Parameter:
3530f6dfbefdSBarry Smith .  snes - the `SNES` context
3531e35cf81dSBarry Smith 
3532e35cf81dSBarry Smith    Output Parameter:
3533e35cf81dSBarry 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
3534e35cf81dSBarry Smith          the Jacobian is built etc.
3535e35cf81dSBarry Smith 
3536dc4c0fb0SBarry Smith    Level: intermediate
3537dc4c0fb0SBarry Smith 
3538e35cf81dSBarry Smith    Notes:
3539e35cf81dSBarry Smith    The default is 1
3540f6dfbefdSBarry Smith 
3541f6dfbefdSBarry Smith    The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3542e35cf81dSBarry Smith 
3543dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3544e35cf81dSBarry Smith 
3545e35cf81dSBarry Smith @*/
3546d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3547d71ae5a4SJacob Faibussowitsch {
3548e35cf81dSBarry Smith   PetscFunctionBegin;
35490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3550e35cf81dSBarry Smith   *lag = snes->lagjacobian;
35513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3552e35cf81dSBarry Smith }
3553e35cf81dSBarry Smith 
355437ec4e1aSPeter Brune /*@
3555f6dfbefdSBarry Smith    SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
355637ec4e1aSPeter Brune 
3557c3339decSBarry Smith    Logically collective
355837ec4e1aSPeter Brune 
3559d8d19677SJose E. Roman    Input Parameters:
3560f6dfbefdSBarry Smith +  snes - the `SNES` context
35619d7e2deaSPeter Brune -   flg - jacobian lagging persists if true
356237ec4e1aSPeter Brune 
356337ec4e1aSPeter Brune    Options Database Keys:
35643d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
35653d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
35663d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
35673d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
35683d5a8a6aSBarry Smith 
3569dc4c0fb0SBarry Smith    Level: advanced
3570dc4c0fb0SBarry Smith 
357195452b02SPatrick Sanan    Notes:
3572f6dfbefdSBarry Smith     Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3573f6dfbefdSBarry Smith 
357495452b02SPatrick Sanan     This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
357537ec4e1aSPeter Brune    several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
357637ec4e1aSPeter Brune    timesteps may present huge efficiency gains.
357737ec4e1aSPeter Brune 
3578dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagJacobianPersists()`
357937ec4e1aSPeter Brune @*/
3580d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3581d71ae5a4SJacob Faibussowitsch {
358237ec4e1aSPeter Brune   PetscFunctionBegin;
358337ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
358437ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
358537ec4e1aSPeter Brune   snes->lagjac_persist = flg;
35863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
358737ec4e1aSPeter Brune }
358837ec4e1aSPeter Brune 
358937ec4e1aSPeter Brune /*@
3590d8e291bfSBarry Smith    SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
359137ec4e1aSPeter Brune 
3592c3339decSBarry Smith    Logically Collective
359337ec4e1aSPeter Brune 
3594d8d19677SJose E. Roman    Input Parameters:
3595f6dfbefdSBarry Smith +  snes - the `SNES` context
35969d7e2deaSPeter Brune -   flg - preconditioner lagging persists if true
359737ec4e1aSPeter Brune 
359837ec4e1aSPeter Brune    Options Database Keys:
35993d5a8a6aSBarry Smith +    -snes_lag_jacobian_persists <true,false> - sets the persistence
36003d5a8a6aSBarry Smith .    -snes_lag_jacobian <-2,1,2,...> - sets the lag
36013d5a8a6aSBarry Smith .    -snes_lag_preconditioner_persists <true,false> - sets the persistence
36023d5a8a6aSBarry Smith -    -snes_lag_preconditioner <-2,1,2,...> - sets the lag
360337ec4e1aSPeter Brune 
3604dc4c0fb0SBarry Smith    Level: developer
3605dc4c0fb0SBarry Smith 
360695452b02SPatrick Sanan    Notes:
3607f6dfbefdSBarry Smith     Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that.
3608f6dfbefdSBarry Smith 
360995452b02SPatrick Sanan    This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
361037ec4e1aSPeter Brune    by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
361137ec4e1aSPeter Brune    several timesteps may present huge efficiency gains.
361237ec4e1aSPeter Brune 
3613dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
361437ec4e1aSPeter Brune @*/
3615d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3616d71ae5a4SJacob Faibussowitsch {
361737ec4e1aSPeter Brune   PetscFunctionBegin;
361837ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
361937ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
362037ec4e1aSPeter Brune   snes->lagpre_persist = flg;
36213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
362237ec4e1aSPeter Brune }
362337ec4e1aSPeter Brune 
36249b94acceSBarry Smith /*@
3625f6dfbefdSBarry Smith    SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3626be5caee7SBarry Smith 
3627c3339decSBarry Smith    Logically Collective
3628be5caee7SBarry Smith 
3629be5caee7SBarry Smith    Input Parameters:
3630f6dfbefdSBarry Smith +  snes - the `SNES` context
3631f6dfbefdSBarry Smith -  force - `PETSC_TRUE` require at least one iteration
3632be5caee7SBarry Smith 
3633f6dfbefdSBarry Smith    Options Database Key:
3634be5caee7SBarry Smith .    -snes_force_iteration <force> - Sets forcing an iteration
3635be5caee7SBarry Smith 
3636dc4c0fb0SBarry Smith    Level: intermediate
3637dc4c0fb0SBarry Smith 
3638f6dfbefdSBarry Smith    Note:
3639f6dfbefdSBarry Smith    This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3640be5caee7SBarry Smith 
3641dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3642be5caee7SBarry Smith @*/
3643d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3644d71ae5a4SJacob Faibussowitsch {
3645be5caee7SBarry Smith   PetscFunctionBegin;
3646be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3647be5caee7SBarry Smith   snes->forceiteration = force;
36483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3649be5caee7SBarry Smith }
3650be5caee7SBarry Smith 
365185216dc7SFande Kong /*@
3652f6dfbefdSBarry Smith    SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
365385216dc7SFande Kong 
3654c3339decSBarry Smith    Logically Collective
365585216dc7SFande Kong 
36562fe279fdSBarry Smith    Input Parameter:
3657f6dfbefdSBarry Smith .  snes - the `SNES` context
365885216dc7SFande Kong 
365985216dc7SFande Kong    Output Parameter:
3660dc4c0fb0SBarry Smith .  force - `PETSC_TRUE` requires at least one iteration.
366185216dc7SFande Kong 
366206dd6b0eSSatish Balay    Level: intermediate
366306dd6b0eSSatish Balay 
3664dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
366585216dc7SFande Kong @*/
3666d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3667d71ae5a4SJacob Faibussowitsch {
366885216dc7SFande Kong   PetscFunctionBegin;
366985216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
367085216dc7SFande Kong   *force = snes->forceiteration;
36713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
367285216dc7SFande Kong }
3673be5caee7SBarry Smith 
3674be5caee7SBarry Smith /*@
3675f6dfbefdSBarry Smith    SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
36769b94acceSBarry Smith 
3677c3339decSBarry Smith    Logically Collective
3678c7afd0dbSLois Curfman McInnes 
36799b94acceSBarry Smith    Input Parameters:
3680f6dfbefdSBarry Smith +  snes - the `SNES` context
368170441072SBarry Smith .  abstol - absolute convergence tolerance
368233174efeSLois Curfman McInnes .  rtol - relative convergence tolerance
36835358d0d4SBarry Smith .  stol -  convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3684f6dfbefdSBarry Smith .  maxit - maximum number of iterations, default 50.
3685f6dfbefdSBarry Smith -  maxf - maximum number of function evaluations (-1 indicates no limit), default 1000
3686fee21e36SBarry Smith 
368733174efeSLois Curfman McInnes    Options Database Keys:
368870441072SBarry Smith +    -snes_atol <abstol> - Sets abstol
3689c7afd0dbSLois Curfman McInnes .    -snes_rtol <rtol> - Sets rtol
3690c7afd0dbSLois Curfman McInnes .    -snes_stol <stol> - Sets stol
3691c7afd0dbSLois Curfman McInnes .    -snes_max_it <maxit> - Sets maxit
3692c7afd0dbSLois Curfman McInnes -    -snes_max_funcs <maxf> - Sets maxf
36939b94acceSBarry Smith 
369436851e7fSLois Curfman McInnes    Level: intermediate
369536851e7fSLois Curfman McInnes 
3696dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
36979b94acceSBarry Smith @*/
3698d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3699d71ae5a4SJacob Faibussowitsch {
37003a40ed3dSBarry Smith   PetscFunctionBegin;
37010700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3702c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3703c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3704c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3705c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3706c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3707c5eb9154SBarry Smith 
370813bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
37095f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3710ab54825eSJed Brown     snes->abstol = abstol;
3711ab54825eSJed Brown   }
371213bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
37135f80ce2aSJacob 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);
3714ab54825eSJed Brown     snes->rtol = rtol;
3715ab54825eSJed Brown   }
371613bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
37175f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3718c60f73f4SPeter Brune     snes->stol = stol;
3719ab54825eSJed Brown   }
3720ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
372163a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3722ab54825eSJed Brown     snes->max_its = maxit;
3723ab54825eSJed Brown   }
3724ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
372563a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3726ab54825eSJed Brown     snes->max_funcs = maxf;
3727ab54825eSJed Brown   }
372888976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
37293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37309b94acceSBarry Smith }
37319b94acceSBarry Smith 
3732e4d06f11SPatrick Farrell /*@
3733f6dfbefdSBarry Smith    SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3734e4d06f11SPatrick Farrell 
3735c3339decSBarry Smith    Logically Collective
3736e4d06f11SPatrick Farrell 
3737e4d06f11SPatrick Farrell    Input Parameters:
3738f6dfbefdSBarry Smith +  snes - the `SNES` context
3739f6dfbefdSBarry Smith -  divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3740e4d06f11SPatrick Farrell 
3741f6dfbefdSBarry Smith    Options Database Key:
3742dc4c0fb0SBarry Smith .    -snes_divergence_tolerance <divtol> - Sets `divtol`
3743e4d06f11SPatrick Farrell 
3744e4d06f11SPatrick Farrell    Level: intermediate
3745e4d06f11SPatrick Farrell 
3746dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3747e4d06f11SPatrick Farrell @*/
3748d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3749d71ae5a4SJacob Faibussowitsch {
3750e4d06f11SPatrick Farrell   PetscFunctionBegin;
3751e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3752e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3753e4d06f11SPatrick Farrell 
375413bcc0bdSJacob Faibussowitsch   if (divtol != (PetscReal)PETSC_DEFAULT) {
3755e4d06f11SPatrick Farrell     snes->divtol = divtol;
37569371c9d4SSatish Balay   } else {
3757e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3758e4d06f11SPatrick Farrell   }
37593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3760e4d06f11SPatrick Farrell }
3761e4d06f11SPatrick Farrell 
37629b94acceSBarry Smith /*@
376333174efeSLois Curfman McInnes    SNESGetTolerances - Gets various parameters used in convergence tests.
376433174efeSLois Curfman McInnes 
3765c7afd0dbSLois Curfman McInnes    Not Collective
3766c7afd0dbSLois Curfman McInnes 
376733174efeSLois Curfman McInnes    Input Parameters:
3768f6dfbefdSBarry Smith +  snes - the `SNES` context
376985385478SLisandro Dalcin .  atol - absolute convergence tolerance
377033174efeSLois Curfman McInnes .  rtol - relative convergence tolerance
377133174efeSLois Curfman McInnes .  stol -  convergence tolerance in terms of the norm
377233174efeSLois Curfman McInnes            of the change in the solution between steps
377333174efeSLois Curfman McInnes .  maxit - maximum number of iterations
3774c7afd0dbSLois Curfman McInnes -  maxf - maximum number of function evaluations
3775fee21e36SBarry Smith 
377636851e7fSLois Curfman McInnes    Level: intermediate
377736851e7fSLois Curfman McInnes 
3778dc4c0fb0SBarry Smith    Note:
3779dc4c0fb0SBarry Smith    The user can specify `NULL` for any parameter that is not needed.
3780dc4c0fb0SBarry Smith 
3781dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetTolerances()`
378233174efeSLois Curfman McInnes @*/
3783d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3784d71ae5a4SJacob Faibussowitsch {
37853a40ed3dSBarry Smith   PetscFunctionBegin;
37860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
378785385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
378833174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3789c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
379033174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
379133174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
37923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
379333174efeSLois Curfman McInnes }
379433174efeSLois Curfman McInnes 
3795e4d06f11SPatrick Farrell /*@
3796e4d06f11SPatrick Farrell    SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3797e4d06f11SPatrick Farrell 
3798e4d06f11SPatrick Farrell    Not Collective
3799e4d06f11SPatrick Farrell 
3800e4d06f11SPatrick Farrell    Input Parameters:
3801f6dfbefdSBarry Smith +  snes - the `SNES` context
3802e4d06f11SPatrick Farrell -  divtol - divergence tolerance
3803e4d06f11SPatrick Farrell 
3804e4d06f11SPatrick Farrell    Level: intermediate
3805e4d06f11SPatrick Farrell 
3806dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetDivergenceTolerance()`
3807e4d06f11SPatrick Farrell @*/
3808d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3809d71ae5a4SJacob Faibussowitsch {
3810e4d06f11SPatrick Farrell   PetscFunctionBegin;
3811e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3812e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
38133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3814e4d06f11SPatrick Farrell }
3815e4d06f11SPatrick Farrell 
381633174efeSLois Curfman McInnes /*@
38179b94acceSBarry Smith    SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
38189b94acceSBarry Smith 
3819c3339decSBarry Smith    Logically Collective
3820fee21e36SBarry Smith 
3821c7afd0dbSLois Curfman McInnes    Input Parameters:
3822f6dfbefdSBarry Smith +  snes - the `SNES` context
3823c7afd0dbSLois Curfman McInnes -  tol - tolerance
3824c7afd0dbSLois Curfman McInnes 
38259b94acceSBarry Smith    Options Database Key:
38264a221d59SStefano Zampini .  -snes_tr_tol <tol> - Sets tol
38279b94acceSBarry Smith 
382836851e7fSLois Curfman McInnes    Level: intermediate
382936851e7fSLois Curfman McInnes 
38304a221d59SStefano Zampini .seealso: [](chapter_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
38319b94acceSBarry Smith @*/
3832d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3833d71ae5a4SJacob Faibussowitsch {
38343a40ed3dSBarry Smith   PetscFunctionBegin;
38350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3836c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
38379b94acceSBarry Smith   snes->deltatol = tol;
38383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38399b94acceSBarry Smith }
38409b94acceSBarry Smith 
38416ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
38426ba87a44SLisandro Dalcin 
3843d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3844d71ae5a4SJacob Faibussowitsch {
3845b271bb04SBarry Smith   PetscDrawLG      lg;
3846b271bb04SBarry Smith   PetscReal        x, y, per;
3847b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3848b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3849b271bb04SBarry Smith   PetscDraw        draw;
3850b271bb04SBarry Smith 
3851459f5d12SBarry Smith   PetscFunctionBegin;
38524d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
38539566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
38549566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38559566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38569566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3857b271bb04SBarry Smith   x = (PetscReal)n;
385877b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
385994c9c6d3SKarl Rupp   else y = -15.0;
38609566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38616934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38629566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38639566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3864b271bb04SBarry Smith   }
3865b271bb04SBarry Smith 
38669566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
38679566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38689566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
3869*aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
38709566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3871b271bb04SBarry Smith   x = (PetscReal)n;
3872b271bb04SBarry Smith   y = 100.0 * per;
38739566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38746934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38759566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38769566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3877b271bb04SBarry Smith   }
3878b271bb04SBarry Smith 
38799566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
38809371c9d4SSatish Balay   if (!n) {
38819371c9d4SSatish Balay     prev = rnorm;
38829371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
38839371c9d4SSatish Balay   }
38849566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38859566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3886b271bb04SBarry Smith   x = (PetscReal)n;
3887b271bb04SBarry Smith   y = (prev - rnorm) / prev;
38889566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38896934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38909566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38919566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3892b271bb04SBarry Smith   }
3893b271bb04SBarry Smith 
38949566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
38959566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38969566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38979566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3898b271bb04SBarry Smith   x = (PetscReal)n;
3899b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3900b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
39019566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3902b271bb04SBarry Smith   }
39036934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39049566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39059566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3906b271bb04SBarry Smith   }
3907b271bb04SBarry Smith   prev = rnorm;
39083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3909b271bb04SBarry Smith }
3910b271bb04SBarry Smith 
3911228d79bcSJed Brown /*@
3912228d79bcSJed Brown    SNESMonitor - runs the user provided monitor routines, if they exist
3913228d79bcSJed Brown 
3914c3339decSBarry Smith    Collective
3915228d79bcSJed Brown 
3916228d79bcSJed Brown    Input Parameters:
3917f6dfbefdSBarry Smith +  snes - nonlinear solver context obtained from `SNESCreate()`
3918228d79bcSJed Brown .  iter - iteration number
3919228d79bcSJed Brown -  rnorm - relative norm of the residual
3920228d79bcSJed Brown 
3921dc4c0fb0SBarry Smith    Level: developer
3922dc4c0fb0SBarry Smith 
3923f6dfbefdSBarry Smith    Note:
3924f6dfbefdSBarry Smith    This routine is called by the `SNES` implementations.
3925228d79bcSJed Brown    It does not typically need to be called by the user.
3926228d79bcSJed Brown 
3927dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESMonitorSet()`
3928228d79bcSJed Brown @*/
3929d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
3930d71ae5a4SJacob Faibussowitsch {
39317a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
39327a03ce2fSLisandro Dalcin 
39337a03ce2fSLisandro Dalcin   PetscFunctionBegin;
39349566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
393548a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
39369566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
39373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39387a03ce2fSLisandro Dalcin }
39397a03ce2fSLisandro Dalcin 
39409b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
39419b94acceSBarry Smith 
3942bf388a1fSBarry Smith /*MC
3943f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
3944bf388a1fSBarry Smith 
3945bf388a1fSBarry Smith      Synopsis:
3946aaa7dc30SBarry Smith      #include <petscsnes.h>
3947bf388a1fSBarry Smith $    PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx)
3948bf388a1fSBarry Smith 
3949c3339decSBarry Smith      Collective
39501843f636SBarry Smith 
39511843f636SBarry Smith     Input Parameters:
3952f6dfbefdSBarry Smith +    snes - the `SNES` context
3953bf388a1fSBarry Smith .    its - iteration number
3954bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
3955bf388a1fSBarry Smith -    mctx - [optional] monitoring context
3956bf388a1fSBarry Smith 
3957878cb397SSatish Balay    Level: advanced
3958878cb397SSatish Balay 
3959dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
3960bf388a1fSBarry Smith M*/
3961bf388a1fSBarry Smith 
39629b94acceSBarry Smith /*@C
3963a6570f20SBarry Smith    SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
39649b94acceSBarry Smith    iteration of the nonlinear solver to display the iteration's
39659b94acceSBarry Smith    progress.
39669b94acceSBarry Smith 
3967c3339decSBarry Smith    Logically Collective
3968fee21e36SBarry Smith 
3969c7afd0dbSLois Curfman McInnes    Input Parameters:
3970f6dfbefdSBarry Smith +  snes - the `SNES` context
397120f4b53cSBarry Smith .  f - the monitor function,  for the calling sequence see `SNESMonitorFunction`
3972b8a78c4aSBarry Smith .  mctx - [optional] user-defined context for private data for the
3973dc4c0fb0SBarry Smith           monitor routine (use `NULL` if no context is desired)
3974dc4c0fb0SBarry Smith -  monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
39759b94acceSBarry Smith 
39769665c990SLois Curfman McInnes    Options Database Keys:
3977f6dfbefdSBarry Smith +    -snes_monitor        - sets `SNESMonitorDefault()`
3978798534f6SMatthew G. Knepley .    -snes_monitor draw::draw_lg - sets line graph monitor,
3979dc4c0fb0SBarry 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
3980c7afd0dbSLois Curfman McInnes                             the options database.
39819665c990SLois Curfman McInnes 
3982dc4c0fb0SBarry Smith    Level: intermediate
3983dc4c0fb0SBarry Smith 
3984f6dfbefdSBarry Smith    Note:
39856bc08f3fSLois Curfman McInnes    Several different monitoring routines may be set by calling
3986f6dfbefdSBarry Smith    `SNESMonitorSet()` multiple times; all will be called in the
39876bc08f3fSLois Curfman McInnes    order in which they were set.
3988639f9d9dSBarry Smith 
3989f6dfbefdSBarry Smith    Fortran Note:
3990f6dfbefdSBarry Smith    Only a single monitor function can be set for each `SNES` object
3991025f1a04SBarry Smith 
3992dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
39939b94acceSBarry Smith @*/
3994d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
3995d71ae5a4SJacob Faibussowitsch {
3996b90d0a6eSBarry Smith   PetscInt  i;
399778064530SBarry Smith   PetscBool identical;
3998b90d0a6eSBarry Smith 
39993a40ed3dSBarry Smith   PetscFunctionBegin;
40000700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4001b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
40029566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
40033ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4004649052a6SBarry Smith   }
40055f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
40066e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4007b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4008639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
40093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40109b94acceSBarry Smith }
40119b94acceSBarry Smith 
4012a278d85bSSatish Balay /*@
4013f6dfbefdSBarry Smith    SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
40145cd90555SBarry Smith 
4015c3339decSBarry Smith    Logically Collective
4016c7afd0dbSLois Curfman McInnes 
40172fe279fdSBarry Smith    Input Parameter:
4018f6dfbefdSBarry Smith .  snes - the `SNES` context
40195cd90555SBarry Smith 
40201a480d89SAdministrator    Options Database Key:
4021a6570f20SBarry Smith .  -snes_monitor_cancel - cancels all monitors that have been hardwired
4022dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4023c7afd0dbSLois Curfman McInnes     set via the options database
40245cd90555SBarry Smith 
4025dc4c0fb0SBarry Smith    Level: intermediate
4026dc4c0fb0SBarry Smith 
4027f6dfbefdSBarry Smith    Note:
4028f6dfbefdSBarry Smith    There is no way to clear one specific monitor from a `SNES` object.
40295cd90555SBarry Smith 
4030dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
40315cd90555SBarry Smith @*/
4032d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4033d71ae5a4SJacob Faibussowitsch {
4034d952e501SBarry Smith   PetscInt i;
4035d952e501SBarry Smith 
40365cd90555SBarry Smith   PetscFunctionBegin;
40370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4038d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
403948a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4040d952e501SBarry Smith   }
40415cd90555SBarry Smith   snes->numbermonitors = 0;
40423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40435cd90555SBarry Smith }
40445cd90555SBarry Smith 
4045bf388a1fSBarry Smith /*MC
4046bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4047bf388a1fSBarry Smith 
4048bf388a1fSBarry Smith      Synopsis:
4049aaa7dc30SBarry Smith      #include <petscsnes.h>
4050bf388a1fSBarry Smith $     PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx)
4051bf388a1fSBarry Smith 
4052c3339decSBarry Smith      Collective
40531843f636SBarry Smith 
40541843f636SBarry Smith     Input Parameters:
4055f6dfbefdSBarry Smith +    snes - the `SNES` context
4056bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4057bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4058bf388a1fSBarry Smith .    gnorm - 2-norm of current step
40591843f636SBarry Smith .    f - 2-norm of function
40601843f636SBarry Smith -    cctx - [optional] convergence context
40611843f636SBarry Smith 
40621843f636SBarry Smith     Output Parameter:
40631843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4064bf388a1fSBarry Smith 
4065878cb397SSatish Balay    Level: intermediate
4066bf388a1fSBarry Smith 
4067dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4068bf388a1fSBarry Smith M*/
4069bf388a1fSBarry Smith 
40709b94acceSBarry Smith /*@C
40719b94acceSBarry Smith    SNESSetConvergenceTest - Sets the function that is to be used
40729b94acceSBarry Smith    to test for convergence of the nonlinear iterative solution.
40739b94acceSBarry Smith 
4074c3339decSBarry Smith    Logically Collective
4075fee21e36SBarry Smith 
4076c7afd0dbSLois Curfman McInnes    Input Parameters:
4077f6dfbefdSBarry Smith +  snes - the `SNES` context
4078f6dfbefdSBarry Smith .  `SNESConvergenceTestFunction` - routine to test for convergence
4079dc4c0fb0SBarry Smith .  cctx - [optional] context for private data for the convergence routine  (may be `NULL`)
4080dc4c0fb0SBarry Smith -  destroy - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
40819b94acceSBarry Smith 
408236851e7fSLois Curfman McInnes    Level: advanced
408336851e7fSLois Curfman McInnes 
4084dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
40859b94acceSBarry Smith @*/
4086d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4087d71ae5a4SJacob Faibussowitsch {
40883a40ed3dSBarry Smith   PetscFunctionBegin;
40890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4090e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
40911baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4092bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
40937f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
409485385478SLisandro Dalcin   snes->cnvP                  = cctx;
40953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40969b94acceSBarry Smith }
40979b94acceSBarry Smith 
409852baeb72SSatish Balay /*@
4099f6dfbefdSBarry Smith    SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4100184914b5SBarry Smith 
4101184914b5SBarry Smith    Not Collective
4102184914b5SBarry Smith 
4103184914b5SBarry Smith    Input Parameter:
4104f6dfbefdSBarry Smith .  snes - the `SNES` context
4105184914b5SBarry Smith 
4106184914b5SBarry Smith    Output Parameter:
4107f6dfbefdSBarry Smith .  reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4108184914b5SBarry Smith 
4109f6dfbefdSBarry Smith    Options Database Key:
41106a4d7782SBarry Smith .   -snes_converged_reason - prints the reason to standard out
41116a4d7782SBarry Smith 
4112184914b5SBarry Smith    Level: intermediate
4113184914b5SBarry Smith 
4114f6dfbefdSBarry Smith    Note:
4115f6dfbefdSBarry Smith     Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4116184914b5SBarry Smith 
4117dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4118184914b5SBarry Smith @*/
4119d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4120d71ae5a4SJacob Faibussowitsch {
4121184914b5SBarry Smith   PetscFunctionBegin;
41220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41234482741eSBarry Smith   PetscValidPointer(reason, 2);
4124184914b5SBarry Smith   *reason = snes->reason;
41253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4126184914b5SBarry Smith }
4127184914b5SBarry Smith 
4128c4421ceaSFande Kong /*@C
4129f6dfbefdSBarry Smith    SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4130c4421ceaSFande Kong 
4131c4421ceaSFande Kong    Not Collective
4132c4421ceaSFande Kong 
4133c4421ceaSFande Kong    Input Parameter:
4134f6dfbefdSBarry Smith .  snes - the `SNES` context
4135c4421ceaSFande Kong 
4136c4421ceaSFande Kong    Output Parameter:
4137dc4c0fb0SBarry Smith .  strreason - a human readable string that describes `SNES` converged reason
4138c4421ceaSFande Kong 
413999c90e12SSatish Balay    Level: beginner
4140c4421ceaSFande Kong 
4141dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetConvergedReason()`
4142c4421ceaSFande Kong @*/
4143d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4144d71ae5a4SJacob Faibussowitsch {
4145c4421ceaSFande Kong   PetscFunctionBegin;
4146c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4147dadcf809SJacob Faibussowitsch   PetscValidPointer(strreason, 2);
4148c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
41493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4150c4421ceaSFande Kong }
4151c4421ceaSFande Kong 
415233866048SMatthew G. Knepley /*@
4153f6dfbefdSBarry Smith    SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
415433866048SMatthew G. Knepley 
415533866048SMatthew G. Knepley    Not Collective
415633866048SMatthew G. Knepley 
415733866048SMatthew G. Knepley    Input Parameters:
4158f6dfbefdSBarry Smith +  snes - the `SNES` context
4159f6dfbefdSBarry Smith -  reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
416033866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
416133866048SMatthew G. Knepley 
4162f6dfbefdSBarry Smith    Level: developer
4163f6dfbefdSBarry Smith 
4164f6dfbefdSBarry Smith    Developer Note:
4165f6dfbefdSBarry Smith    Called inside the various `SNESSolve()` implementations
416633866048SMatthew G. Knepley 
4167dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
416833866048SMatthew G. Knepley @*/
4169d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4170d71ae5a4SJacob Faibussowitsch {
417133866048SMatthew G. Knepley   PetscFunctionBegin;
417233866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
417333866048SMatthew G. Knepley   snes->reason = reason;
41743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
417533866048SMatthew G. Knepley }
417633866048SMatthew G. Knepley 
4177c9005455SLois Curfman McInnes /*@
4178c9005455SLois Curfman McInnes    SNESSetConvergenceHistory - Sets the array used to hold the convergence history.
4179c9005455SLois Curfman McInnes 
4180c3339decSBarry Smith    Logically Collective
4181fee21e36SBarry Smith 
4182c7afd0dbSLois Curfman McInnes    Input Parameters:
4183f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
41848c7482ecSBarry Smith .  a   - array to hold history, this array will contain the function norms computed at each step
4185cd5578b5SBarry Smith .  its - integer array holds the number of linear iterations for each solve.
4186758f92a0SBarry Smith .  na  - size of a and its
4187f6dfbefdSBarry Smith -  reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4188758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4189c7afd0dbSLois Curfman McInnes 
4190dc4c0fb0SBarry Smith    Level: intermediate
4191dc4c0fb0SBarry Smith 
4192308dcc3eSBarry Smith    Notes:
4193dc4c0fb0SBarry Smith    If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4194308dcc3eSBarry Smith    default array of length 10000 is allocated.
4195308dcc3eSBarry Smith 
4196c9005455SLois Curfman McInnes    This routine is useful, e.g., when running a code for purposes
4197c9005455SLois Curfman McInnes    of accurate performance monitoring, when no I/O should be done
4198c9005455SLois Curfman McInnes    during the section of code that is being timed.
4199c9005455SLois Curfman McInnes 
4200dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4201c9005455SLois Curfman McInnes @*/
4202d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4203d71ae5a4SJacob Faibussowitsch {
42043a40ed3dSBarry Smith   PetscFunctionBegin;
42050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4206064a246eSJacob Faibussowitsch   if (a) PetscValidRealPointer(a, 2);
4207a562a398SLisandro Dalcin   if (its) PetscValidIntPointer(its, 3);
42087a1ec6d4SBarry Smith   if (!a) {
4209308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
42109566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4211071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4212308dcc3eSBarry Smith   }
4213c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4214758f92a0SBarry Smith   snes->conv_hist_its   = its;
4215115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4216a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4217758f92a0SBarry Smith   snes->conv_hist_reset = reset;
42183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4219758f92a0SBarry Smith }
4220758f92a0SBarry Smith 
4221d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4222c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4223c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
422499e0435eSBarry Smith 
4225d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4226d71ae5a4SJacob Faibussowitsch {
4227308dcc3eSBarry Smith   mxArray   *mat;
4228308dcc3eSBarry Smith   PetscInt   i;
4229308dcc3eSBarry Smith   PetscReal *ar;
4230308dcc3eSBarry Smith 
4231308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4232308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4233f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
423411cc89d2SBarry Smith   return mat;
4235308dcc3eSBarry Smith }
4236308dcc3eSBarry Smith #endif
4237308dcc3eSBarry Smith 
42380c4c9dddSBarry Smith /*@C
4239758f92a0SBarry Smith    SNESGetConvergenceHistory - Gets the array used to hold the convergence history.
4240758f92a0SBarry Smith 
42413f9fe445SBarry Smith    Not Collective
4242758f92a0SBarry Smith 
4243758f92a0SBarry Smith    Input Parameter:
4244f6dfbefdSBarry Smith .  snes - iterative context obtained from `SNESCreate()`
4245758f92a0SBarry Smith 
4246758f92a0SBarry Smith    Output Parameters:
4247f6dfbefdSBarry Smith +  a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4248758f92a0SBarry Smith .  its - integer array holds the number of linear iterations (or
4249758f92a0SBarry Smith          negative if not converged) for each solve.
425020f4b53cSBarry Smith -  na  - size of `a` and `its`
4251758f92a0SBarry Smith 
4252dc4c0fb0SBarry Smith    Level: intermediate
4253dc4c0fb0SBarry Smith 
425420f4b53cSBarry Smith    Note:
425520f4b53cSBarry Smith    This routine is useful, e.g., when running a code for purposes
425620f4b53cSBarry Smith    of accurate performance monitoring, when no I/O should be done
425720f4b53cSBarry Smith    during the section of code that is being timed.
425820f4b53cSBarry Smith 
425920f4b53cSBarry Smith    Fortran Note:
4260758f92a0SBarry Smith     The calling sequence for this routine in Fortran is
4261dc4c0fb0SBarry Smith .vb
4262dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4263dc4c0fb0SBarry Smith .ve
4264758f92a0SBarry Smith 
4265dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4266758f92a0SBarry Smith @*/
4267d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4268d71ae5a4SJacob Faibussowitsch {
4269758f92a0SBarry Smith   PetscFunctionBegin;
42700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4271758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4272758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4273115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
42743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4275c9005455SLois Curfman McInnes }
4276c9005455SLois Curfman McInnes 
4277ac226902SBarry Smith /*@C
427876b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4279eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
42807e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
428176b2cf59SMatthew Knepley 
4282c3339decSBarry Smith   Logically Collective
428376b2cf59SMatthew Knepley 
428476b2cf59SMatthew Knepley   Input Parameters:
4285a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4286a2b725a8SWilliam Gropp - func - The function
428776b2cf59SMatthew Knepley 
428820f4b53cSBarry Smith   Calling sequence of `func`:
428920f4b53cSBarry Smith $ PetscErrorCode func(SNES snes, PetscInt step);
429020f4b53cSBarry Smith + snes - the nonlinear solver context
429120f4b53cSBarry Smith - step - The current step of the iteration
429276b2cf59SMatthew Knepley 
4293fe97e370SBarry Smith   Level: advanced
4294fe97e370SBarry Smith 
42956b7fb656SBarry Smith   Note:
4296f6dfbefdSBarry 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
4297f6dfbefdSBarry Smith      to `SNESSetFunction()`, or `SNESSetPicard()`
4298fe97e370SBarry Smith      This is not used by most users.
429976b2cf59SMatthew Knepley 
4300*aaa8cc7dSPierre Jolivet      There are a variety of function hooks one many set that are called at different stages of the nonlinear solution process, see the functions listed below.
43016b7fb656SBarry Smith 
4302dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESSolve()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4303db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
430476b2cf59SMatthew Knepley @*/
4305d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt))
4306d71ae5a4SJacob Faibussowitsch {
430776b2cf59SMatthew Knepley   PetscFunctionBegin;
43080700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4309e7788613SBarry Smith   snes->ops->update = func;
43103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
431176b2cf59SMatthew Knepley }
431276b2cf59SMatthew Knepley 
43139b94acceSBarry Smith /*
43149b94acceSBarry Smith    SNESScaleStep_Private - Scales a step so that its length is less than the
43159b94acceSBarry Smith    positive parameter delta.
43169b94acceSBarry Smith 
43179b94acceSBarry Smith     Input Parameters:
4318f6dfbefdSBarry Smith +   snes - the `SNES` context
43199b94acceSBarry Smith .   y - approximate solution of linear system
43209b94acceSBarry Smith .   fnorm - 2-norm of current function
4321c7afd0dbSLois Curfman McInnes -   delta - trust region size
43229b94acceSBarry Smith 
43239b94acceSBarry Smith     Output Parameters:
4324c7afd0dbSLois Curfman McInnes +   gpnorm - predicted function norm at the new point, assuming local
43259b94acceSBarry Smith     linearization.  The value is zero if the step lies within the trust
43269b94acceSBarry Smith     region, and exceeds zero otherwise.
4327c7afd0dbSLois Curfman McInnes -   ynorm - 2-norm of the step
43289b94acceSBarry Smith 
4329f6dfbefdSBarry Smith     Level: developer
43309b94acceSBarry Smith 
4331f6dfbefdSBarry Smith     Note:
4332f6dfbefdSBarry Smith     For non-trust region methods such as `SNESNEWTONLS`, the parameter delta
4333f6dfbefdSBarry Smith     is set to be the maximum allowable step size.
43349b94acceSBarry Smith */
4335d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESScaleStep_Private(SNES snes, Vec y, PetscReal *fnorm, PetscReal *delta, PetscReal *gpnorm, PetscReal *ynorm)
4336d71ae5a4SJacob Faibussowitsch {
4337064f8208SBarry Smith   PetscReal   nrm;
4338ea709b57SSatish Balay   PetscScalar cnorm;
43393a40ed3dSBarry Smith 
43403a40ed3dSBarry Smith   PetscFunctionBegin;
43410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43420700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 2);
4343c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 2);
4344184914b5SBarry Smith 
43459566063dSJacob Faibussowitsch   PetscCall(VecNorm(y, NORM_2, &nrm));
4346064f8208SBarry Smith   if (nrm > *delta) {
4347064f8208SBarry Smith     nrm     = *delta / nrm;
4348064f8208SBarry Smith     *gpnorm = (1.0 - nrm) * (*fnorm);
4349064f8208SBarry Smith     cnorm   = nrm;
43509566063dSJacob Faibussowitsch     PetscCall(VecScale(y, cnorm));
43519b94acceSBarry Smith     *ynorm = *delta;
43529b94acceSBarry Smith   } else {
43539b94acceSBarry Smith     *gpnorm = 0.0;
4354064f8208SBarry Smith     *ynorm  = nrm;
43559b94acceSBarry Smith   }
43563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43579b94acceSBarry Smith }
43589b94acceSBarry Smith 
435991f3e32bSBarry Smith /*@C
4360f6dfbefdSBarry Smith    SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
43612a359c20SBarry Smith 
4362c3339decSBarry Smith    Collective
43632a359c20SBarry Smith 
43642a359c20SBarry Smith    Parameter:
4365f6dfbefdSBarry Smith +  snes - iterative context obtained from `SNESCreate()`
43662a359c20SBarry Smith -  viewer - the viewer to display the reason
43672a359c20SBarry Smith 
43682a359c20SBarry Smith    Options Database Keys:
4369ee300463SSatish Balay +  -snes_converged_reason - print reason for converged or diverged, also prints number of iterations
4370ee300463SSatish Balay -  -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4371eafd5ff0SAlex Lindsay 
4372f6dfbefdSBarry Smith   Note:
4373f6dfbefdSBarry Smith      To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4374f6dfbefdSBarry Smith      use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
43752a359c20SBarry Smith 
43762a359c20SBarry Smith    Level: beginner
43772a359c20SBarry Smith 
4378dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4379f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4380f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4381db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
43822a359c20SBarry Smith @*/
4383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4384d71ae5a4SJacob Faibussowitsch {
438575cca76cSMatthew G. Knepley   PetscViewerFormat format;
43862a359c20SBarry Smith   PetscBool         isAscii;
43872a359c20SBarry Smith 
43882a359c20SBarry Smith   PetscFunctionBegin;
438919a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
43909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
43912a359c20SBarry Smith   if (isAscii) {
43929566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
43939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
439475cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
439575cca76cSMatthew G. Knepley       DM       dm;
439675cca76cSMatthew G. Knepley       Vec      u;
439775cca76cSMatthew G. Knepley       PetscDS  prob;
439875cca76cSMatthew G. Knepley       PetscInt Nf, f;
439995cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
440095cbbfd3SMatthew G. Knepley       void    **exactCtx;
440175cca76cSMatthew G. Knepley       PetscReal error;
440275cca76cSMatthew G. Knepley 
44039566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
44049566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
44059566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
44069566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
44079566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
44089566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
44099566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
44109566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
44119566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
441263a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
441375cca76cSMatthew G. Knepley     }
4414eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
44152a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
441663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
44172a359c20SBarry Smith       } else {
441863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44192a359c20SBarry Smith       }
4420eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
44212a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
442263a3b9bcSJacob 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));
44232a359c20SBarry Smith       } else {
442463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44252a359c20SBarry Smith       }
44262a359c20SBarry Smith     }
44279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
44282a359c20SBarry Smith   }
44293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44302a359c20SBarry Smith }
44312a359c20SBarry Smith 
4432c4421ceaSFande Kong /*@C
4433c4421ceaSFande Kong    SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4434*aaa8cc7dSPierre Jolivet     end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4435c4421ceaSFande Kong 
4436c3339decSBarry Smith    Logically Collective
4437c4421ceaSFande Kong 
4438c4421ceaSFande Kong    Input Parameters:
4439f6dfbefdSBarry Smith +  snes - the `SNES` context
4440c4421ceaSFande Kong .  f - the snes converged reason view function
4441c4421ceaSFande Kong .  vctx - [optional] user-defined context for private data for the
4442dc4c0fb0SBarry Smith           snes converged reason view routine (use `NULL` if no context is desired)
4443dc4c0fb0SBarry Smith -  reasonviewdestroy - [optional] routine that frees reasonview context (may be `NULL`)
4444c4421ceaSFande Kong 
4445c4421ceaSFande Kong    Options Database Keys:
4446f6dfbefdSBarry Smith +    -snes_converged_reason        - sets a default `SNESConvergedReasonView()`
4447c4421ceaSFande Kong -    -snes_converged_reason_view_cancel - cancels all converged reason viewers that have
4448c4421ceaSFande Kong                             been hardwired into a code by
4449f6dfbefdSBarry Smith                             calls to `SNESConvergedReasonViewSet()`, but
4450c4421ceaSFande Kong                             does not cancel those set via
4451c4421ceaSFande Kong                             the options database.
4452c4421ceaSFande Kong 
4453dc4c0fb0SBarry Smith    Level: intermediate
4454dc4c0fb0SBarry Smith 
4455f6dfbefdSBarry Smith    Note:
4456c4421ceaSFande Kong    Several different converged reason view routines may be set by calling
4457f6dfbefdSBarry Smith    `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4458c4421ceaSFande Kong    order in which they were set.
4459c4421ceaSFande Kong 
4460dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4461c4421ceaSFande Kong @*/
4462d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES, void *), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **))
4463d71ae5a4SJacob Faibussowitsch {
4464c4421ceaSFande Kong   PetscInt  i;
4465c4421ceaSFande Kong   PetscBool identical;
4466c4421ceaSFande Kong 
4467c4421ceaSFande Kong   PetscFunctionBegin;
4468c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4469c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
44709566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
44713ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4472c4421ceaSFande Kong   }
44735f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4474c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4475c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4476c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
44773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4478c4421ceaSFande Kong }
4479c4421ceaSFande Kong 
448091f3e32bSBarry Smith /*@
4481f6dfbefdSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed.
4482c4421ceaSFande Kong                                        All the user-provided convergedReasonView routines will be involved as well, if they exist.
44832a359c20SBarry Smith 
4484c3339decSBarry Smith   Collective
44852a359c20SBarry Smith 
44862fe279fdSBarry Smith   Input Parameter:
4487f6dfbefdSBarry Smith . snes   - the `SNES` object
44882a359c20SBarry Smith 
4489f6dfbefdSBarry Smith   Level: advanced
44902a359c20SBarry Smith 
4491dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4492f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
44932a359c20SBarry Smith @*/
4494d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4495d71ae5a4SJacob Faibussowitsch {
44962a359c20SBarry Smith   PetscViewer       viewer;
44972a359c20SBarry Smith   PetscBool         flg;
44982a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
44992a359c20SBarry Smith   PetscViewerFormat format;
4500c4421ceaSFande Kong   PetscInt          i;
45012a359c20SBarry Smith 
45022a359c20SBarry Smith   PetscFunctionBegin;
45033ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
45042a359c20SBarry Smith   incall = PETSC_TRUE;
4505c4421ceaSFande Kong 
4506c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
450748a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4508c4421ceaSFande Kong 
4509c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
45109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
45112a359c20SBarry Smith   if (flg) {
45129566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
45139566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
45149566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
45159566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
45162a359c20SBarry Smith   }
45172a359c20SBarry Smith   incall = PETSC_FALSE;
45183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45192a359c20SBarry Smith }
45202a359c20SBarry Smith 
4521487a658cSBarry Smith /*@
4522f69a0ea3SMatthew Knepley    SNESSolve - Solves a nonlinear system F(x) = b.
4523f6dfbefdSBarry Smith    Call `SNESSolve()` after calling `SNESCreate()` and optional routines of the form `SNESSetXXX()`.
45249b94acceSBarry Smith 
4525c3339decSBarry Smith    Collective
4526c7afd0dbSLois Curfman McInnes 
4527b2002411SLois Curfman McInnes    Input Parameters:
4528f6dfbefdSBarry Smith +  snes - the `SNES` context
4529dc4c0fb0SBarry Smith .  b - the constant part of the equation F(x) = b, or `NULL` to use zero.
453085385478SLisandro Dalcin -  x - the solution vector.
45319b94acceSBarry Smith 
4532dc4c0fb0SBarry Smith    Level: beginner
4533dc4c0fb0SBarry Smith 
4534f6dfbefdSBarry Smith    Note:
45358ddd3da0SLois Curfman McInnes    The user should initialize the vector,x, with the initial guess
4536f6dfbefdSBarry Smith    for the nonlinear solve prior to calling `SNESSolve()`.  In particular,
45378ddd3da0SLois Curfman McInnes    to employ an initial guess of zero, the user should explicitly set
4538f6dfbefdSBarry Smith    this vector to zero by calling `VecSet()`.
45398ddd3da0SLois Curfman McInnes 
4540dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4541db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4542db781477SPatrick Sanan           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`
45439b94acceSBarry Smith @*/
4544d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4545d71ae5a4SJacob Faibussowitsch {
4546ace3abfcSBarry Smith   PetscBool flg;
4547efd51863SBarry Smith   PetscInt  grid;
45480298fd71SBarry Smith   Vec       xcreated = NULL;
4549caa4e7f2SJed Brown   DM        dm;
4550052efed2SBarry Smith 
45513a40ed3dSBarry Smith   PetscFunctionBegin;
45520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4553a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4554a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
45550700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
455685385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
455785385478SLisandro Dalcin 
455834b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
455906fc46c8SMatthew G. Knepley   {
456006fc46c8SMatthew G. Knepley     PetscViewer       viewer;
456106fc46c8SMatthew G. Knepley     PetscViewerFormat format;
45627c88af5aSMatthew G. Knepley     PetscInt          num;
456306fc46c8SMatthew G. Knepley     PetscBool         flg;
456406fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
456506fc46c8SMatthew G. Knepley 
456606fc46c8SMatthew G. Knepley     if (!incall) {
456734b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
45689566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
456906fc46c8SMatthew G. Knepley       if (flg) {
457006fc46c8SMatthew G. Knepley         PetscConvEst conv;
457146079b62SMatthew G. Knepley         DM           dm;
457246079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
457346079b62SMatthew G. Knepley         PetscInt     Nf;
457406fc46c8SMatthew G. Knepley 
457506fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
45769566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
45779566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
45789566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
45799566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
45809566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
45819566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
45829566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
45839566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
45849566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
45859566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
45869566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
45879566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
45889566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
45899566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
459006fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
459106fc46c8SMatthew G. Knepley       }
459234b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4593b2588ea6SMatthew G. Knepley       num = 1;
45949566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
459534b4d3a8SMatthew G. Knepley       if (flg) {
459634b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
459734b4d3a8SMatthew G. Knepley 
459834b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
45999566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46009566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46019566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46029566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46039566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46049566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
46059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
460634b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
460734b4d3a8SMatthew G. Knepley       }
46087c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
46097c88af5aSMatthew G. Knepley       num = 0;
46109566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
46117c88af5aSMatthew G. Knepley       if (num) {
46127c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
46137c88af5aSMatthew G. Knepley 
46147c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
46159566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46169566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46179566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46189566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46199566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46209566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
46219566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
46227c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
46237c88af5aSMatthew G. Knepley       }
462406fc46c8SMatthew G. Knepley     }
462506fc46c8SMatthew G. Knepley   }
4626ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4627caa4e7f2SJed Brown   if (!x) {
46289566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
46299566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4630a69afd8bSBarry Smith     x = xcreated;
4631a69afd8bSBarry Smith   }
46329566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4633f05ece33SBarry Smith 
46349566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4635efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
463685385478SLisandro Dalcin     /* set solution vector */
46379566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
46389566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
463985385478SLisandro Dalcin     snes->vec_sol = x;
46409566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4641caa4e7f2SJed Brown 
4642caa4e7f2SJed Brown     /* set affine vector if provided */
46439566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
46449566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
464585385478SLisandro Dalcin     snes->vec_rhs = b;
464685385478SLisandro Dalcin 
46475f80ce2aSJacob 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");
46485f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
46495f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector");
4650aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
46519566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
46529566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
46533f149594SLisandro Dalcin 
46547eee914bSBarry Smith     if (!grid) {
465525e27a38SBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4656dd568438SSatish Balay     }
4657d25893d9SBarry Smith 
4658abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
46599371c9d4SSatish Balay     if (snes->counters_reset) {
46609371c9d4SSatish Balay       snes->nfuncs      = 0;
46619371c9d4SSatish Balay       snes->linear_its  = 0;
46629371c9d4SSatish Balay       snes->numFailures = 0;
46639371c9d4SSatish Balay     }
4664d5e45103SBarry Smith 
46659566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4666dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
46679566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
46685f80ce2aSJacob Faibussowitsch     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver returned without setting converged reason");
4669422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
46703f149594SLisandro Dalcin 
467137ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
467237ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
467337ec4e1aSPeter Brune 
46749566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
46759566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4676c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
46779566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
46785968eb51SBarry Smith 
46795f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
46809c8e83a9SBarry Smith     if (snes->reason < 0) break;
4681efd51863SBarry Smith     if (grid < snes->gridsequence) {
4682efd51863SBarry Smith       DM  fine;
4683efd51863SBarry Smith       Vec xnew;
4684efd51863SBarry Smith       Mat interp;
4685efd51863SBarry Smith 
46869566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
46875f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
46889566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
46899566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
46909566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
46919566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
46929566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4693efd51863SBarry Smith       x = xnew;
4694efd51863SBarry Smith 
46959566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
46969566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
46979566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
46989566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
46999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4700efd51863SBarry Smith     }
4701efd51863SBarry Smith   }
47029566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
47039566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
47049566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
47059566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
47063f7e2da0SPeter Brune 
47079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
47089566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
47093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47109b94acceSBarry Smith }
47119b94acceSBarry Smith 
47129b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
47139b94acceSBarry Smith 
471482bf6240SBarry Smith /*@C
47154b0e389bSBarry Smith    SNESSetType - Sets the method for the nonlinear solver.
47169b94acceSBarry Smith 
4717c3339decSBarry Smith    Collective
4718fee21e36SBarry Smith 
4719c7afd0dbSLois Curfman McInnes    Input Parameters:
4720f6dfbefdSBarry Smith +  snes - the `SNES` context
4721454a90a3SBarry Smith -  type - a known method
4722c7afd0dbSLois Curfman McInnes 
4723c7afd0dbSLois Curfman McInnes    Options Database Key:
4724454a90a3SBarry Smith .  -snes_type <type> - Sets the method; use -help for a list
472504d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4726ae12b187SLois Curfman McInnes 
4727dc4c0fb0SBarry Smith   Level: intermediate
4728dc4c0fb0SBarry Smith 
47299b94acceSBarry Smith    Notes:
4730e090d566SSatish Balay    See "petsc/include/petscsnes.h" for available methods (for instance)
4731f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4732c7afd0dbSLois Curfman McInnes      (systems of nonlinear equations)
47334a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4734c7afd0dbSLois Curfman McInnes      (systems of nonlinear equations)
47359b94acceSBarry Smith 
4736f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4737f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4738ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4739ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4740f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4741ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4742ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4743ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4744ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4745b0a32e0cSBarry Smith   appropriate method.
474636851e7fSLois Curfman McInnes 
4747f6dfbefdSBarry Smith     Developer Note:
4748f6dfbefdSBarry Smith     `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4749f6dfbefdSBarry Smith     the constructor in that list and calls it to create the specific object.
47508f6c3df8SBarry Smith 
4751dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
47529b94acceSBarry Smith @*/
4753d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4754d71ae5a4SJacob Faibussowitsch {
4755ace3abfcSBarry Smith   PetscBool match;
47565f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
47573a40ed3dSBarry Smith 
47583a40ed3dSBarry Smith   PetscFunctionBegin;
47590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47604482741eSBarry Smith   PetscValidCharPointer(type, 2);
476182bf6240SBarry Smith 
47629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
47633ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
476492ff6ae8SBarry Smith 
47659566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
47665f80ce2aSJacob Faibussowitsch   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
476775396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4768dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
476975396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
47709e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
47719e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
47729e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
47739e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
47749e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
47757fe760d5SStefano Zampini 
47767fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
47779566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
47787fe760d5SStefano Zampini 
477975396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
478075396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4781f5af7f23SKarl Rupp 
47829566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
47839566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
47843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47859b94acceSBarry Smith }
47869b94acceSBarry Smith 
47879b94acceSBarry Smith /*@C
4788f6dfbefdSBarry Smith    SNESGetType - Gets the `SNES` method type and name (as a string).
47899b94acceSBarry Smith 
4790c7afd0dbSLois Curfman McInnes    Not Collective
4791c7afd0dbSLois Curfman McInnes 
47929b94acceSBarry Smith    Input Parameter:
47934b0e389bSBarry Smith .  snes - nonlinear solver context
47949b94acceSBarry Smith 
47959b94acceSBarry Smith    Output Parameter:
4796f6dfbefdSBarry Smith .  type - `SNES` method (a character string)
47979b94acceSBarry Smith 
479836851e7fSLois Curfman McInnes    Level: intermediate
479936851e7fSLois Curfman McInnes 
4800dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
48019b94acceSBarry Smith @*/
4802d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4803d71ae5a4SJacob Faibussowitsch {
48043a40ed3dSBarry Smith   PetscFunctionBegin;
48050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48064482741eSBarry Smith   PetscValidPointer(type, 2);
48077adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
48083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48099b94acceSBarry Smith }
48109b94acceSBarry Smith 
48113cd8a7caSMatthew G. Knepley /*@
4812f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
48133cd8a7caSMatthew G. Knepley 
4814c3339decSBarry Smith   Logically Collective
48153cd8a7caSMatthew G. Knepley 
48163cd8a7caSMatthew G. Knepley   Input Parameters:
4817f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
48183cd8a7caSMatthew G. Knepley - u    - the solution vector
48193cd8a7caSMatthew G. Knepley 
48203cd8a7caSMatthew G. Knepley   Level: beginner
48213cd8a7caSMatthew G. Knepley 
4822dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
48233cd8a7caSMatthew G. Knepley @*/
4824d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4825d71ae5a4SJacob Faibussowitsch {
48263cd8a7caSMatthew G. Knepley   DM dm;
48273cd8a7caSMatthew G. Knepley 
48283cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
48293cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48303cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
48319566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
48329566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
48333cd8a7caSMatthew G. Knepley 
48343cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
48353cd8a7caSMatthew G. Knepley 
48369566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
48379566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
48383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48393cd8a7caSMatthew G. Knepley }
48403cd8a7caSMatthew G. Knepley 
484152baeb72SSatish Balay /*@
48429b94acceSBarry Smith    SNESGetSolution - Returns the vector where the approximate solution is
4843f6dfbefdSBarry Smith    stored. This is the fine grid solution when using `SNESSetGridSequence()`.
48449b94acceSBarry Smith 
4845f6dfbefdSBarry Smith    Not Collective, but x is parallel if snes is parallel
4846c7afd0dbSLois Curfman McInnes 
48479b94acceSBarry Smith    Input Parameter:
4848f6dfbefdSBarry Smith .  snes - the `SNES` context
48499b94acceSBarry Smith 
48509b94acceSBarry Smith    Output Parameter:
48519b94acceSBarry Smith .  x - the solution
48529b94acceSBarry Smith 
485370e92668SMatthew Knepley    Level: intermediate
485436851e7fSLois Curfman McInnes 
4855dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
48569b94acceSBarry Smith @*/
4857d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4858d71ae5a4SJacob Faibussowitsch {
48593a40ed3dSBarry Smith   PetscFunctionBegin;
48600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48614482741eSBarry Smith   PetscValidPointer(x, 2);
486285385478SLisandro Dalcin   *x = snes->vec_sol;
48633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
486470e92668SMatthew Knepley }
486570e92668SMatthew Knepley 
486652baeb72SSatish Balay /*@
48679b94acceSBarry Smith    SNESGetSolutionUpdate - Returns the vector where the solution update is
48689b94acceSBarry Smith    stored.
48699b94acceSBarry Smith 
4870f6dfbefdSBarry Smith    Not Collective, but x is parallel if snes is parallel
4871c7afd0dbSLois Curfman McInnes 
48729b94acceSBarry Smith    Input Parameter:
4873f6dfbefdSBarry Smith .  snes - the `SNES` context
48749b94acceSBarry Smith 
48759b94acceSBarry Smith    Output Parameter:
48769b94acceSBarry Smith .  x - the solution update
48779b94acceSBarry Smith 
487836851e7fSLois Curfman McInnes    Level: advanced
487936851e7fSLois Curfman McInnes 
4880dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
48819b94acceSBarry Smith @*/
4882d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4883d71ae5a4SJacob Faibussowitsch {
48843a40ed3dSBarry Smith   PetscFunctionBegin;
48850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48864482741eSBarry Smith   PetscValidPointer(x, 2);
488785385478SLisandro Dalcin   *x = snes->vec_sol_update;
48883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48899b94acceSBarry Smith }
48909b94acceSBarry Smith 
48919b94acceSBarry Smith /*@C
4892f6dfbefdSBarry Smith    SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
48939b94acceSBarry Smith 
4894f6dfbefdSBarry Smith    Not Collective, but r is parallel if snes is parallel. Collective if r is requested, but has not been created yet.
4895c7afd0dbSLois Curfman McInnes 
48969b94acceSBarry Smith    Input Parameter:
4897f6dfbefdSBarry Smith .  snes - the `SNES` context
48989b94acceSBarry Smith 
4899d8d19677SJose E. Roman    Output Parameters:
4900dc4c0fb0SBarry Smith +  r - the vector that is used to store residuals (or `NULL` if you don't want it)
490120f4b53cSBarry Smith .  f - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunction`
4902dc4c0fb0SBarry Smith -  ctx - the function context (or `NULL` if you don't want it)
49039b94acceSBarry Smith 
490436851e7fSLois Curfman McInnes    Level: advanced
490536851e7fSLois Curfman McInnes 
4906f6dfbefdSBarry Smith     Note:
4907dc4c0fb0SBarry Smith    The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
490804edfde5SBarry Smith 
4909dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction`
49109b94acceSBarry Smith @*/
4911d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4912d71ae5a4SJacob Faibussowitsch {
49136cab3a1bSJed Brown   DM dm;
4914a63bb30eSJed Brown 
49153a40ed3dSBarry Smith   PetscFunctionBegin;
49160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4917a63bb30eSJed Brown   if (r) {
4918a63bb30eSJed Brown     if (!snes->vec_func) {
4919a63bb30eSJed Brown       if (snes->vec_rhs) {
49209566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
4921a63bb30eSJed Brown       } else if (snes->vec_sol) {
49229566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
4923a63bb30eSJed Brown       } else if (snes->dm) {
49249566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
4925a63bb30eSJed Brown       }
4926a63bb30eSJed Brown     }
4927a63bb30eSJed Brown     *r = snes->vec_func;
4928a63bb30eSJed Brown   }
49299566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49309566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
49313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49329b94acceSBarry Smith }
49339b94acceSBarry Smith 
4934c79ef259SPeter Brune /*@C
4935f6dfbefdSBarry Smith    SNESGetNGS - Returns the `SNESNGS` function and context set with `SNESSetNGS()`
4936c79ef259SPeter Brune 
4937c79ef259SPeter Brune    Input Parameter:
4938f6dfbefdSBarry Smith .  snes - the `SNES` context
4939c79ef259SPeter Brune 
4940d8d19677SJose E. Roman    Output Parameters:
4941dc4c0fb0SBarry Smith +  f - the function (or `NULL`) see `SNESNGSFunction` for details
4942dc4c0fb0SBarry Smith -  ctx    - the function context (or `NULL`)
4943c79ef259SPeter Brune 
4944c79ef259SPeter Brune    Level: advanced
4945c79ef259SPeter Brune 
4946dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetNGS()`, `SNESGetFunction()`
4947c79ef259SPeter Brune @*/
4948c79ef259SPeter Brune 
4949d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4950d71ae5a4SJacob Faibussowitsch {
49516cab3a1bSJed Brown   DM dm;
49526cab3a1bSJed Brown 
4953646217ecSPeter Brune   PetscFunctionBegin;
4954646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49559566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49569566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
49573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4958646217ecSPeter Brune }
4959646217ecSPeter Brune 
49603c7409f5SSatish Balay /*@C
49613c7409f5SSatish Balay    SNESSetOptionsPrefix - Sets the prefix used for searching for all
4962f6dfbefdSBarry Smith    `SNES` options in the database.
49633c7409f5SSatish Balay 
4964c3339decSBarry Smith    Logically Collective
4965fee21e36SBarry Smith 
4966d8d19677SJose E. Roman    Input Parameters:
4967f6dfbefdSBarry Smith +  snes - the `SNES` context
4968c7afd0dbSLois Curfman McInnes -  prefix - the prefix to prepend to all option names
4969c7afd0dbSLois Curfman McInnes 
4970dc4c0fb0SBarry Smith    Level: advanced
4971dc4c0fb0SBarry Smith 
4972f6dfbefdSBarry Smith    Note:
4973a83b1b31SSatish Balay    A hyphen (-) must NOT be given at the beginning of the prefix name.
4974c7afd0dbSLois Curfman McInnes    The first character of all runtime options is AUTOMATICALLY the hyphen.
4975d850072dSLois Curfman McInnes 
4976dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
49773c7409f5SSatish Balay @*/
4978d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
4979d71ae5a4SJacob Faibussowitsch {
49803a40ed3dSBarry Smith   PetscFunctionBegin;
49810700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
49839566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
498435f5d045SPeter Brune   if (snes->linesearch) {
49859566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
49869566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
498735f5d045SPeter Brune   }
49889566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
49893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49903c7409f5SSatish Balay }
49913c7409f5SSatish Balay 
49923c7409f5SSatish Balay /*@C
4993f525115eSLois Curfman McInnes    SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
4994f6dfbefdSBarry Smith    `SNES` options in the database.
49953c7409f5SSatish Balay 
4996c3339decSBarry Smith    Logically Collective
4997fee21e36SBarry Smith 
4998c7afd0dbSLois Curfman McInnes    Input Parameters:
4999f6dfbefdSBarry Smith +  snes - the `SNES` context
5000c7afd0dbSLois Curfman McInnes -  prefix - the prefix to prepend to all option names
5001c7afd0dbSLois Curfman McInnes 
5002dc4c0fb0SBarry Smith    Level: advanced
5003dc4c0fb0SBarry Smith 
5004f6dfbefdSBarry Smith    Note:
5005a83b1b31SSatish Balay    A hyphen (-) must NOT be given at the beginning of the prefix name.
5006c7afd0dbSLois Curfman McInnes    The first character of all runtime options is AUTOMATICALLY the hyphen.
5007d850072dSLois Curfman McInnes 
5008dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
50093c7409f5SSatish Balay @*/
5010d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5011d71ae5a4SJacob Faibussowitsch {
50123a40ed3dSBarry Smith   PetscFunctionBegin;
50130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50149566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
50159566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
501635f5d045SPeter Brune   if (snes->linesearch) {
50179566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50189566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
501935f5d045SPeter Brune   }
50209566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
50213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50223c7409f5SSatish Balay }
50233c7409f5SSatish Balay 
50249ab63eb5SSatish Balay /*@C
5025f6dfbefdSBarry Smith    SNESGetOptionsPrefix - Gets the prefix used for searching for all
5026f6dfbefdSBarry Smith    `SNES` options in the database.
50273c7409f5SSatish Balay 
5028c7afd0dbSLois Curfman McInnes    Not Collective
5029c7afd0dbSLois Curfman McInnes 
50303c7409f5SSatish Balay    Input Parameter:
5031f6dfbefdSBarry Smith .  snes - the `SNES` context
50323c7409f5SSatish Balay 
50333c7409f5SSatish Balay    Output Parameter:
50343c7409f5SSatish Balay .  prefix - pointer to the prefix string used
50353c7409f5SSatish Balay 
503636851e7fSLois Curfman McInnes    Level: advanced
503736851e7fSLois Curfman McInnes 
5038dc4c0fb0SBarry Smith    Fortran Note:
5039dc4c0fb0SBarry Smith     The user should pass in a string 'prefix' of
5040dc4c0fb0SBarry Smith    sufficient length to hold the prefix.
5041dc4c0fb0SBarry Smith 
5042dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
50433c7409f5SSatish Balay @*/
5044d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5045d71ae5a4SJacob Faibussowitsch {
50463a40ed3dSBarry Smith   PetscFunctionBegin;
50470700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
50493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50503c7409f5SSatish Balay }
50513c7409f5SSatish Balay 
50523cea93caSBarry Smith /*@C
50531c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
50541c84c290SBarry Smith 
505520f4b53cSBarry Smith    Not Collective
50561c84c290SBarry Smith 
50571c84c290SBarry Smith    Input Parameters:
505820f4b53cSBarry Smith +  sname - name of a new user-defined solver
505920f4b53cSBarry Smith -  function - routine to create method context
50601c84c290SBarry Smith 
5061dc4c0fb0SBarry Smith    Level: advanced
5062dc4c0fb0SBarry Smith 
5063f6dfbefdSBarry Smith    Note:
5064f6dfbefdSBarry Smith    `SNESRegister()` may be called multiple times to add several user-defined solvers.
50651c84c290SBarry Smith 
50661c84c290SBarry Smith    Sample usage:
50671c84c290SBarry Smith .vb
5068bdf89e91SBarry Smith    SNESRegister("my_solver",MySolverCreate);
50691c84c290SBarry Smith .ve
50701c84c290SBarry Smith 
50711c84c290SBarry Smith    Then, your solver can be chosen with the procedural interface via
50721c84c290SBarry Smith $     SNESSetType(snes,"my_solver")
50731c84c290SBarry Smith    or at runtime via the option
50741c84c290SBarry Smith $     -snes_type my_solver
50751c84c290SBarry Smith 
5076dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
50773cea93caSBarry Smith @*/
5078d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5079d71ae5a4SJacob Faibussowitsch {
5080b2002411SLois Curfman McInnes   PetscFunctionBegin;
50819566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
50829566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
50833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5084b2002411SLois Curfman McInnes }
5085da9b6338SBarry Smith 
5086d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5087d71ae5a4SJacob Faibussowitsch {
508877431f27SBarry Smith   PetscInt    N, i, j;
5089da9b6338SBarry Smith   Vec         u, uh, fh;
5090da9b6338SBarry Smith   PetscScalar value;
5091da9b6338SBarry Smith   PetscReal   norm;
5092da9b6338SBarry Smith 
5093da9b6338SBarry Smith   PetscFunctionBegin;
50949566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
50959566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
50969566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5097da9b6338SBarry Smith 
5098da9b6338SBarry Smith   /* currently only works for sequential */
50999566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
51009566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5101da9b6338SBarry Smith   for (i = 0; i < N; i++) {
51029566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
510363a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5104da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
51058b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
51069566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
51079566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
51089566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
510963a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5110da9b6338SBarry Smith       value = -value;
51119566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5112da9b6338SBarry Smith     }
5113da9b6338SBarry Smith   }
51149566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
51159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
51163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5117da9b6338SBarry Smith }
511871f87433Sdalcinl 
511971f87433Sdalcinl /*@
5120f6dfbefdSBarry Smith    SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
512171f87433Sdalcinl    computing relative tolerance for linear solvers within an inexact
512271f87433Sdalcinl    Newton method.
512371f87433Sdalcinl 
5124c3339decSBarry Smith    Logically Collective
512571f87433Sdalcinl 
512671f87433Sdalcinl    Input Parameters:
5127f6dfbefdSBarry Smith +  snes - `SNES` context
5128f6dfbefdSBarry Smith -  flag - `PETSC_TRUE` or `PETSC_FALSE`
512971f87433Sdalcinl 
5130f6dfbefdSBarry Smith     Options Database Keys:
513164ba62caSBarry Smith +  -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence
513264ba62caSBarry Smith .  -snes_ksp_ew_version ver - version of  Eisenstat-Walker method
513364ba62caSBarry Smith .  -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0
513464ba62caSBarry Smith .  -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax
513564ba62caSBarry Smith .  -snes_ksp_ew_gamma <gamma> - Sets gamma
513664ba62caSBarry Smith .  -snes_ksp_ew_alpha <alpha> - Sets alpha
513764ba62caSBarry Smith .  -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2
513864ba62caSBarry Smith -  -snes_ksp_ew_threshold <threshold> - Sets threshold
513964ba62caSBarry Smith 
5140dc4c0fb0SBarry Smith    Level: advanced
5141dc4c0fb0SBarry Smith 
5142f6dfbefdSBarry Smith    Note:
5143f6dfbefdSBarry Smith    The default is to use a constant relative tolerance for
514471f87433Sdalcinl    the inner linear solvers.  Alternatively, one can use the
514571f87433Sdalcinl    Eisenstat-Walker method, where the relative convergence tolerance
514671f87433Sdalcinl    is reset at each Newton iteration according progress of the nonlinear
514771f87433Sdalcinl    solver.
514871f87433Sdalcinl 
514971f87433Sdalcinl    Reference:
5150f6dfbefdSBarry Smith .  - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996.
515171f87433Sdalcinl 
5152dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
515371f87433Sdalcinl @*/
5154d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5155d71ae5a4SJacob Faibussowitsch {
515671f87433Sdalcinl   PetscFunctionBegin;
51570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5158acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
515971f87433Sdalcinl   snes->ksp_ewconv = flag;
51603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
516171f87433Sdalcinl }
516271f87433Sdalcinl 
516371f87433Sdalcinl /*@
5164f6dfbefdSBarry Smith    SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
516571f87433Sdalcinl    for computing relative tolerance for linear solvers within an
516671f87433Sdalcinl    inexact Newton method.
516771f87433Sdalcinl 
516871f87433Sdalcinl    Not Collective
516971f87433Sdalcinl 
517071f87433Sdalcinl    Input Parameter:
5171f6dfbefdSBarry Smith .  snes - `SNES` context
517271f87433Sdalcinl 
517371f87433Sdalcinl    Output Parameter:
5174f6dfbefdSBarry Smith .  flag - `PETSC_TRUE` or `PETSC_FALSE`
517571f87433Sdalcinl 
517671f87433Sdalcinl    Level: advanced
517771f87433Sdalcinl 
5178dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
517971f87433Sdalcinl @*/
5180d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5181d71ae5a4SJacob Faibussowitsch {
518271f87433Sdalcinl   PetscFunctionBegin;
51830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5184534a8f05SLisandro Dalcin   PetscValidBoolPointer(flag, 2);
518571f87433Sdalcinl   *flag = snes->ksp_ewconv;
51863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
518771f87433Sdalcinl }
518871f87433Sdalcinl 
518971f87433Sdalcinl /*@
5190fa9f3622SBarry Smith    SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
519171f87433Sdalcinl    convergence criteria for the linear solvers within an inexact
519271f87433Sdalcinl    Newton method.
519371f87433Sdalcinl 
5194c3339decSBarry Smith    Logically Collective
519571f87433Sdalcinl 
519671f87433Sdalcinl    Input Parameters:
5197f6dfbefdSBarry Smith +    snes - `SNES` context
51980f0abf79SStefano Zampini .    version - version 1, 2 (default is 2), 3 or 4
519971f87433Sdalcinl .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
520071f87433Sdalcinl .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
520171f87433Sdalcinl .    gamma - multiplicative factor for version 2 rtol computation
520271f87433Sdalcinl              (0 <= gamma2 <= 1)
520371f87433Sdalcinl .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
520471f87433Sdalcinl .    alpha2 - power for safeguard
520571f87433Sdalcinl -    threshold - threshold for imposing safeguard (0 < threshold < 1)
520671f87433Sdalcinl 
5207dc4c0fb0SBarry Smith    Level: advanced
5208dc4c0fb0SBarry Smith 
5209f6dfbefdSBarry Smith    Notes:
521071f87433Sdalcinl    Version 3 was contributed by Luis Chacon, June 2006.
521171f87433Sdalcinl 
5212f6dfbefdSBarry Smith    Use `PETSC_DEFAULT` to retain the default for any of the parameters.
521371f87433Sdalcinl 
5214dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
521571f87433Sdalcinl @*/
5216d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5217d71ae5a4SJacob Faibussowitsch {
5218fa9f3622SBarry Smith   SNESKSPEW *kctx;
52195fd66863SKarl Rupp 
522071f87433Sdalcinl   PetscFunctionBegin;
52210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5222fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52235f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5224c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5225c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5226c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5227c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5228c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5229c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5230c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
523171f87433Sdalcinl 
523271f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
523313bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
523413bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
523513bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
523613bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
523713bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
523813bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
523971f87433Sdalcinl 
52400f0abf79SStefano 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);
52410b121fc5SBarry 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);
52420b121fc5SBarry 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);
52430b121fc5SBarry 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);
52440b121fc5SBarry 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);
52450b121fc5SBarry 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);
52463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
524771f87433Sdalcinl }
524871f87433Sdalcinl 
524971f87433Sdalcinl /*@
5250fa9f3622SBarry Smith    SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
525171f87433Sdalcinl    convergence criteria for the linear solvers within an inexact
525271f87433Sdalcinl    Newton method.
525371f87433Sdalcinl 
525471f87433Sdalcinl    Not Collective
525571f87433Sdalcinl 
525697bb3fdcSJose E. Roman    Input Parameter:
5257f6dfbefdSBarry Smith .    snes - `SNES` context
525871f87433Sdalcinl 
525971f87433Sdalcinl    Output Parameters:
52600f0abf79SStefano Zampini +    version - version 1, 2 (default is 2), 3 or 4
526171f87433Sdalcinl .    rtol_0 - initial relative tolerance (0 <= rtol_0 < 1)
526271f87433Sdalcinl .    rtol_max - maximum relative tolerance (0 <= rtol_max < 1)
5263bf388a1fSBarry Smith .    gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
526471f87433Sdalcinl .    alpha - power for version 2 rtol computation (1 < alpha <= 2)
526571f87433Sdalcinl .    alpha2 - power for safeguard
526671f87433Sdalcinl -    threshold - threshold for imposing safeguard (0 < threshold < 1)
526771f87433Sdalcinl 
526871f87433Sdalcinl    Level: advanced
526971f87433Sdalcinl 
5270dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
527171f87433Sdalcinl @*/
5272d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5273d71ae5a4SJacob Faibussowitsch {
5274fa9f3622SBarry Smith   SNESKSPEW *kctx;
52755fd66863SKarl Rupp 
527671f87433Sdalcinl   PetscFunctionBegin;
52770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5278fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52795f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
528071f87433Sdalcinl   if (version) *version = kctx->version;
528171f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
528271f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
528371f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
528471f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
528571f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
528671f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
52873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
528871f87433Sdalcinl }
528971f87433Sdalcinl 
5290d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5291d71ae5a4SJacob Faibussowitsch {
5292fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
529371f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
529471f87433Sdalcinl 
529571f87433Sdalcinl   PetscFunctionBegin;
52963ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
529730058271SDmitry Karpeev   if (!snes->iter) {
529830058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
52999566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
53000f0abf79SStefano Zampini   } else {
53010fdf79fbSJacob 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);
530271f87433Sdalcinl     if (kctx->version == 1) {
53030f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
530485ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
530571f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
530671f87433Sdalcinl     } else if (kctx->version == 2) {
530785ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
530885ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
530971f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
531071f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
531185ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
531271f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
531385ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
531471f87433Sdalcinl       stol = PetscMax(rtol, stol);
531571f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
531671f87433Sdalcinl       /* safeguard: avoid oversolving */
531730058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
531871f87433Sdalcinl       stol = PetscMax(rtol, stol);
531971f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
53200fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
53210fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
53220f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
53230f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
53240f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
53250f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
53260f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
53270f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
53280f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
53290f0abf79SStefano Zampini 
5330a4598233SStefano Zampini       if (kctx->rtol_last_2 > kctx->v4_m3 && kctx->rtol_last > kctx->v4_m3 && kctx->rk_last_2 < kctx->v4_p1 && kctx->rk_last < kctx->v4_p1) rtol = kctx->v4_m4 * kctx->rtol_last;
53310f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
53320f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
53330f0abf79SStefano Zampini       kctx->rk_last     = rk;
53340fdf79fbSJacob Faibussowitsch     }
53350f0abf79SStefano Zampini   }
53360f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
533771f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
53389566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
533963a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
53403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
534171f87433Sdalcinl }
534271f87433Sdalcinl 
5343d71ae5a4SJacob Faibussowitsch PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes)
5344d71ae5a4SJacob Faibussowitsch {
5345fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
534671f87433Sdalcinl   PCSide     pcside;
534771f87433Sdalcinl   Vec        lres;
534871f87433Sdalcinl 
534971f87433Sdalcinl   PetscFunctionBegin;
53503ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
53519566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
535271dbe336SPeter Brune   kctx->norm_last = snes->norm;
53530f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
53544f00ce20SMatthew G. Knepley     PC        pc;
53550f0abf79SStefano Zampini     PetscBool getRes;
53564f00ce20SMatthew G. Knepley 
53579566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
53580f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
53590f0abf79SStefano Zampini     if (!getRes) {
53600f0abf79SStefano Zampini       KSPNormType normtype;
53610f0abf79SStefano Zampini 
53620f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
53630f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
53640f0abf79SStefano Zampini     }
53659566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
53660f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
53679566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
536871f87433Sdalcinl     } else {
536971f87433Sdalcinl       /* KSP residual is preconditioned residual */
537071f87433Sdalcinl       /* compute true linear residual norm */
53710f0abf79SStefano Zampini       Mat J;
53720f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
53739566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
53740f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
53759566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
53769566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
53779566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
537871f87433Sdalcinl     }
537971f87433Sdalcinl   }
53803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
538171f87433Sdalcinl }
538271f87433Sdalcinl 
5383d4211eb9SBarry Smith /*@
5384f6dfbefdSBarry Smith    SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5385d4211eb9SBarry Smith 
5386f6dfbefdSBarry Smith    Not Collective, but if snes is parallel, then ksp is parallel
5387d4211eb9SBarry Smith 
5388d4211eb9SBarry Smith    Input Parameter:
5389f6dfbefdSBarry Smith .  snes - the `SNES` context
5390d4211eb9SBarry Smith 
5391d4211eb9SBarry Smith    Output Parameter:
5392f6dfbefdSBarry Smith .  ksp - the `KSP` context
5393d4211eb9SBarry Smith 
5394dc4c0fb0SBarry Smith    Level: beginner
5395dc4c0fb0SBarry Smith 
5396d4211eb9SBarry Smith    Notes:
5397f6dfbefdSBarry Smith    The user can then directly manipulate the `KSP` context to set various
5398d4211eb9SBarry Smith    options, etc.  Likewise, the user can then extract and manipulate the
5399f6dfbefdSBarry Smith    `PC` contexts as well.
5400f6dfbefdSBarry Smith 
5401f6dfbefdSBarry Smith    Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5402d4211eb9SBarry Smith 
5403dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5404d4211eb9SBarry Smith @*/
5405d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5406d71ae5a4SJacob Faibussowitsch {
540771f87433Sdalcinl   PetscFunctionBegin;
5408d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5409d4211eb9SBarry Smith   PetscValidPointer(ksp, 2);
5410d4211eb9SBarry Smith 
5411d4211eb9SBarry Smith   if (!snes->ksp) {
54129566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
54139566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5414d4211eb9SBarry Smith 
54159566063dSJacob Faibussowitsch     PetscCall(KSPSetPreSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPreSolve_SNESEW, snes));
54169566063dSJacob Faibussowitsch     PetscCall(KSPSetPostSolve(snes->ksp, (PetscErrorCode(*)(KSP, Vec, Vec, void *))KSPPostSolve_SNESEW, snes));
5417a5c2985bSBarry Smith 
54189566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
54199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5420d4211eb9SBarry Smith   }
5421d4211eb9SBarry Smith   *ksp = snes->ksp;
54223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
542371f87433Sdalcinl }
54246c699258SBarry Smith 
5425af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
54266c699258SBarry Smith /*@
5427f6dfbefdSBarry Smith    SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
54286c699258SBarry Smith 
5429c3339decSBarry Smith    Logically Collective
54306c699258SBarry Smith 
54316c699258SBarry Smith    Input Parameters:
54322a808120SBarry Smith +  snes - the nonlinear solver context
5433dc4c0fb0SBarry Smith -  dm - the dm, cannot be `NULL`
5434dc4c0fb0SBarry Smith 
5435dc4c0fb0SBarry Smith    Level: intermediate
54366c699258SBarry Smith 
5437f6dfbefdSBarry Smith    Note:
5438f6dfbefdSBarry Smith    A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5439f6dfbefdSBarry Smith    even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5440e03a659cSJed Brown    problems using the same function space.
5441e03a659cSJed Brown 
5442dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `DM`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
54436c699258SBarry Smith @*/
5444d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5445d71ae5a4SJacob Faibussowitsch {
5446345fed2cSBarry Smith   KSP    ksp;
5447942e3340SBarry Smith   DMSNES sdm;
54486c699258SBarry Smith 
54496c699258SBarry Smith   PetscFunctionBegin;
54500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54512a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
54529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5453942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
545451f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
54559566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
54569566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5457f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
54586cab3a1bSJed Brown     }
54599566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
54609566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
54616cab3a1bSJed Brown   }
54626c699258SBarry Smith   snes->dm     = dm;
5463116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5464f5af7f23SKarl Rupp 
54659566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
54669566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
54679566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5468efd4aadfSBarry Smith   if (snes->npc) {
54699566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
54709566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
54712c155ee1SBarry Smith   }
54723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54736c699258SBarry Smith }
54746c699258SBarry Smith 
54756c699258SBarry Smith /*@
5476f6dfbefdSBarry Smith    SNESGetDM - Gets the `DM` that may be used by some preconditioners
54776c699258SBarry Smith 
5478f6dfbefdSBarry Smith    Not Collective but dm obtained is parallel on snes
54796c699258SBarry Smith 
54806c699258SBarry Smith    Input Parameter:
54816c699258SBarry Smith . snes - the preconditioner context
54826c699258SBarry Smith 
54836c699258SBarry Smith    Output Parameter:
54846c699258SBarry Smith .  dm - the dm
54856c699258SBarry Smith 
54866c699258SBarry Smith    Level: intermediate
54876c699258SBarry Smith 
5488dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `DM`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
54896c699258SBarry Smith @*/
5490d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5491d71ae5a4SJacob Faibussowitsch {
54926c699258SBarry Smith   PetscFunctionBegin;
54930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54946cab3a1bSJed Brown   if (!snes->dm) {
54959566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5496116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
54976cab3a1bSJed Brown   }
54986c699258SBarry Smith   *dm = snes->dm;
54993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55006c699258SBarry Smith }
55010807856dSBarry Smith 
550231823bd8SMatthew G Knepley /*@
5503be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
550431823bd8SMatthew G Knepley 
5505c3339decSBarry Smith   Collective
550631823bd8SMatthew G Knepley 
550731823bd8SMatthew G Knepley   Input Parameters:
5508f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5509f6dfbefdSBarry Smith - npc   - the preconditioner object
551031823bd8SMatthew G Knepley 
5511dc4c0fb0SBarry Smith   Level: developer
5512dc4c0fb0SBarry Smith 
551331823bd8SMatthew G Knepley   Notes:
5514f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
551531823bd8SMatthew G Knepley   to configure it using the API).
551631823bd8SMatthew G Knepley 
5517f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5518f6dfbefdSBarry Smith 
5519dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
552031823bd8SMatthew G Knepley @*/
5521d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5522d71ae5a4SJacob Faibussowitsch {
552331823bd8SMatthew G Knepley   PetscFunctionBegin;
552431823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5525f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5526f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5527f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
55289566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5529f6dfbefdSBarry Smith   snes->npc = npc;
55303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
553131823bd8SMatthew G Knepley }
553231823bd8SMatthew G Knepley 
553331823bd8SMatthew G Knepley /*@
5534f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
553531823bd8SMatthew G Knepley 
5536f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
553731823bd8SMatthew G Knepley 
553831823bd8SMatthew G Knepley   Input Parameter:
5539f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
554031823bd8SMatthew G Knepley 
554131823bd8SMatthew G Knepley   Output Parameter:
5542f6dfbefdSBarry Smith . npc - preconditioner context
554331823bd8SMatthew G Knepley 
5544f6dfbefdSBarry Smith   Options Database Key:
5545f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5546b5badacbSBarry Smith 
5547dc4c0fb0SBarry Smith   Level: developer
5548dc4c0fb0SBarry Smith 
554995452b02SPatrick Sanan   Notes:
5550f6dfbefdSBarry Smith     If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5551be95d8f1SBarry Smith 
5552f6dfbefdSBarry Smith     The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5553f6dfbefdSBarry Smith     `SNES`
5554951fe5abSBarry Smith 
5555dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
555631823bd8SMatthew G Knepley @*/
5557d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5558d71ae5a4SJacob Faibussowitsch {
5559a64e098fSPeter Brune   const char *optionsprefix;
556031823bd8SMatthew G Knepley 
556131823bd8SMatthew G Knepley   PetscFunctionBegin;
556231823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
556331823bd8SMatthew G Knepley   PetscValidPointer(pc, 2);
5564efd4aadfSBarry Smith   if (!snes->npc) {
5565ec785e5bSStefano Zampini     void *ctx;
5566ec785e5bSStefano Zampini 
55679566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
55689566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
55699566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
55709566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
55719566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5572ec785e5bSStefano Zampini     PetscCall(SNESGetApplicationContext(snes, &ctx));
5573ec785e5bSStefano Zampini     PetscCall(SNESSetApplicationContext(snes->npc, ctx));
55749566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
557531823bd8SMatthew G Knepley   }
5576efd4aadfSBarry Smith   *pc = snes->npc;
55773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
557831823bd8SMatthew G Knepley }
557931823bd8SMatthew G Knepley 
55803ad1a0b9SPatrick Farrell /*@
55813ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
55823ad1a0b9SPatrick Farrell 
55833ad1a0b9SPatrick Farrell   Not Collective
55843ad1a0b9SPatrick Farrell 
55853ad1a0b9SPatrick Farrell   Input Parameter:
5586f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
55873ad1a0b9SPatrick Farrell 
55883ad1a0b9SPatrick Farrell   Output Parameter:
5589f6dfbefdSBarry Smith . has_npc - whether the `SNES` has an NPC or not
55903ad1a0b9SPatrick Farrell 
55913ad1a0b9SPatrick Farrell   Level: developer
55923ad1a0b9SPatrick Farrell 
5593dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESSetNPC()`, `SNESGetNPC()`
55943ad1a0b9SPatrick Farrell @*/
5595d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5596d71ae5a4SJacob Faibussowitsch {
55973ad1a0b9SPatrick Farrell   PetscFunctionBegin;
55983ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5599efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
56003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56013ad1a0b9SPatrick Farrell }
56023ad1a0b9SPatrick Farrell 
5603c40d0f55SPeter Brune /*@
5604be95d8f1SBarry Smith     SNESSetNPCSide - Sets the preconditioning side.
5605c40d0f55SPeter Brune 
5606c3339decSBarry Smith     Logically Collective
5607c40d0f55SPeter Brune 
5608c40d0f55SPeter Brune     Input Parameter:
5609f6dfbefdSBarry Smith .   snes - iterative context obtained from `SNESCreate()`
5610c40d0f55SPeter Brune 
5611c40d0f55SPeter Brune     Output Parameter:
5612c40d0f55SPeter Brune .   side - the preconditioning side, where side is one of
5613c40d0f55SPeter Brune .vb
56142d547940SBarry Smith       PC_LEFT - left preconditioning
56152d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5616c40d0f55SPeter Brune .ve
5617c40d0f55SPeter Brune 
5618f6dfbefdSBarry Smith     Options Database Key:
561967b8a455SSatish Balay .   -snes_npc_side <right,left> - nonlinear preconditioner side
5620c40d0f55SPeter Brune 
5621dc4c0fb0SBarry Smith     Level: intermediate
5622dc4c0fb0SBarry Smith 
5623f6dfbefdSBarry Smith     Note:
5624f6dfbefdSBarry Smith     `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
56252d547940SBarry Smith 
5626dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`
5627c40d0f55SPeter Brune @*/
5628d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5629d71ae5a4SJacob Faibussowitsch {
5630c40d0f55SPeter Brune   PetscFunctionBegin;
5631c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5632c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5633b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
563454c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5635efd4aadfSBarry Smith   snes->npcside = side;
56363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5637c40d0f55SPeter Brune }
5638c40d0f55SPeter Brune 
5639c40d0f55SPeter Brune /*@
5640be95d8f1SBarry Smith     SNESGetNPCSide - Gets the preconditioning side.
5641c40d0f55SPeter Brune 
5642c40d0f55SPeter Brune     Not Collective
5643c40d0f55SPeter Brune 
5644c40d0f55SPeter Brune     Input Parameter:
5645f6dfbefdSBarry Smith .   snes - iterative context obtained from `SNESCreate()`
5646c40d0f55SPeter Brune 
5647c40d0f55SPeter Brune     Output Parameter:
5648c40d0f55SPeter Brune .   side - the preconditioning side, where side is one of
5649c40d0f55SPeter Brune .vb
5650f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5651f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5652c40d0f55SPeter Brune .ve
5653c40d0f55SPeter Brune 
5654c40d0f55SPeter Brune     Level: intermediate
5655c40d0f55SPeter Brune 
5656dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`
5657c40d0f55SPeter Brune @*/
5658d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5659d71ae5a4SJacob Faibussowitsch {
5660c40d0f55SPeter Brune   PetscFunctionBegin;
5661c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5662c40d0f55SPeter Brune   PetscValidPointer(side, 2);
5663efd4aadfSBarry Smith   *side = snes->npcside;
56643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5665c40d0f55SPeter Brune }
5666c40d0f55SPeter Brune 
56679e764e56SPeter Brune /*@
5668f6dfbefdSBarry Smith   SNESSetLineSearch - Sets the linesearch on the `SNES` instance.
56699e764e56SPeter Brune 
5670c3339decSBarry Smith   Collective
56719e764e56SPeter Brune 
56729e764e56SPeter Brune   Input Parameters:
5673f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
56749e764e56SPeter Brune - linesearch   - the linesearch object
56759e764e56SPeter Brune 
5676dc4c0fb0SBarry Smith   Level: developer
5677dc4c0fb0SBarry Smith 
5678f6dfbefdSBarry Smith   Note:
5679f6dfbefdSBarry Smith   Use `SNESGetLineSearch()` to retrieve the preconditioner context (for example,
56809e764e56SPeter Brune   to configure it using the API).
56819e764e56SPeter Brune 
5682dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESGetLineSearch()`
56839e764e56SPeter Brune @*/
5684d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5685d71ae5a4SJacob Faibussowitsch {
56869e764e56SPeter Brune   PetscFunctionBegin;
56879e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5688f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
56899e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
56909566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
56919566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5692f5af7f23SKarl Rupp 
56939e764e56SPeter Brune   snes->linesearch = linesearch;
5694f5af7f23SKarl Rupp 
56953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56969e764e56SPeter Brune }
56979e764e56SPeter Brune 
5698a34ceb2aSJed Brown /*@
5699dc4c0fb0SBarry Smith   SNESGetLineSearch - Returns the line search context set with `SNESSetLineSearch()`
5700f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
57019e764e56SPeter Brune 
57029e764e56SPeter Brune   Not Collective
57039e764e56SPeter Brune 
57049e764e56SPeter Brune   Input Parameter:
5705f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57069e764e56SPeter Brune 
57079e764e56SPeter Brune   Output Parameter:
57089e764e56SPeter Brune . linesearch - linesearch context
57099e764e56SPeter Brune 
5710162e0bf5SPeter Brune   Level: beginner
57119e764e56SPeter Brune 
5712dc4c0fb0SBarry Smith .seealso: [](chapter_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
57139e764e56SPeter Brune @*/
5714d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5715d71ae5a4SJacob Faibussowitsch {
57169e764e56SPeter Brune   const char *optionsprefix;
57179e764e56SPeter Brune 
57189e764e56SPeter Brune   PetscFunctionBegin;
57199e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57209e764e56SPeter Brune   PetscValidPointer(linesearch, 2);
57219e764e56SPeter Brune   if (!snes->linesearch) {
57229566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57239566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
57249566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
57259566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
57269566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
57279e764e56SPeter Brune   }
57289e764e56SPeter Brune   *linesearch = snes->linesearch;
57293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57309e764e56SPeter Brune }
5731