xref: /petsc/src/snes/interface/snes.c (revision 420bcc1b905230dede3c88f397d1a4e60493adde)
1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h"  I*/
207475bc1SBarry Smith #include <petscdmshell.h>
3d96771aaSLisandro Dalcin #include <petscdraw.h>
4a01aa210SMatthew G. Knepley #include <petscds.h>
534b4d3a8SMatthew G. Knepley #include <petscdmadaptor.h>
606fc46c8SMatthew G. Knepley #include <petscconvest.h>
79b94acceSBarry Smith 
8ace3abfcSBarry Smith PetscBool         SNESRegisterAllCalled = PETSC_FALSE;
90298fd71SBarry Smith PetscFunctionList SNESList              = NULL;
108ba1e511SMatthew Knepley 
118ba1e511SMatthew Knepley /* Logging support */
1222c6f798SBarry Smith PetscClassId  SNES_CLASSID, DMSNES_CLASSID;
13fc8bc0e3SRichard Tran Mills PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval;
14a09944afSBarry Smith 
15e113a28aSBarry Smith /*@
16dc4c0fb0SBarry Smith   SNESSetErrorIfNotConverged - Causes `SNESSolve()` to generate an error immediately if the solver has not converged.
17e113a28aSBarry Smith 
18c3339decSBarry Smith   Logically Collective
19e113a28aSBarry Smith 
20e113a28aSBarry Smith   Input Parameters:
21f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
22f6dfbefdSBarry Smith - flg  - `PETSC_TRUE` indicates you want the error generated
23e113a28aSBarry Smith 
2420f4b53cSBarry Smith   Options Database Key:
2567b8a455SSatish Balay . -snes_error_if_not_converged <true,false> - cause an immediate error condition and stop the program if the solver does not converge
26e113a28aSBarry Smith 
27e113a28aSBarry Smith   Level: intermediate
28e113a28aSBarry Smith 
29f6dfbefdSBarry Smith   Note:
30f6dfbefdSBarry Smith   Normally PETSc continues if a solver fails to converge, you can call `SNESGetConvergedReason()` after a `SNESSolve()`
31f6dfbefdSBarry Smith   to determine if it has converged. Otherwise the solution may be inaccurate or wrong
32e113a28aSBarry Smith 
331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
34e113a28aSBarry Smith @*/
35d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetErrorIfNotConverged(SNES snes, PetscBool flg)
36d71ae5a4SJacob Faibussowitsch {
37e113a28aSBarry Smith   PetscFunctionBegin;
38e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flg, 2);
40e113a28aSBarry Smith   snes->errorifnotconverged = flg;
413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42e113a28aSBarry Smith }
43e113a28aSBarry Smith 
44e113a28aSBarry Smith /*@
45f6dfbefdSBarry Smith   SNESGetErrorIfNotConverged - Indicates if `SNESSolve()` will generate an error if the solver does not converge?
46e113a28aSBarry Smith 
47e113a28aSBarry Smith   Not Collective
48e113a28aSBarry Smith 
49e113a28aSBarry Smith   Input Parameter:
50f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
51e113a28aSBarry Smith 
52e113a28aSBarry Smith   Output Parameter:
53f6dfbefdSBarry Smith . flag - `PETSC_TRUE` if it will generate an error, else `PETSC_FALSE`
54e113a28aSBarry Smith 
55e113a28aSBarry Smith   Level: intermediate
56e113a28aSBarry Smith 
571cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetErrorIfNotConverged()`, `KSPGetErrorIfNotConverged()`, `KSPSetErrorIfNotConverged()`
58e113a28aSBarry Smith @*/
59d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetErrorIfNotConverged(SNES snes, PetscBool *flag)
60d71ae5a4SJacob Faibussowitsch {
61e113a28aSBarry Smith   PetscFunctionBegin;
62e113a28aSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
634f572ea9SToby Isaac   PetscAssertPointer(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 
83*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `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 
106*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSolve()`, `SNESSetAlwaysComputesFinalResidual()`
1074fc747eaSLawrence Mitchell @*/
108d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg)
109d71ae5a4SJacob Faibussowitsch {
1104fc747eaSLawrence Mitchell   PetscFunctionBegin;
1114fc747eaSLawrence Mitchell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1124fc747eaSLawrence Mitchell   *flg = snes->alwayscomputesfinalresidual;
1133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1144fc747eaSLawrence Mitchell }
1154fc747eaSLawrence Mitchell 
116e725d27bSBarry Smith /*@
117f6dfbefdSBarry Smith   SNESSetFunctionDomainError - tells `SNES` that the input vector, a proposed new solution, to your function you provided to `SNESSetFunction()` is not
118f0b84518SBarry Smith   in the functions domain. For example, a step with negative pressure.
1194936397dSBarry Smith 
120c3339decSBarry Smith   Logically Collective
1214936397dSBarry Smith 
1222fe279fdSBarry Smith   Input Parameter:
123f6dfbefdSBarry Smith . snes - the `SNES` context
1244936397dSBarry Smith 
12528529972SSatish Balay   Level: advanced
1264936397dSBarry Smith 
127ced0f3aeSBarry Smith   Notes:
128ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
129ced0f3aeSBarry Smith 
130ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
131ced0f3aeSBarry Smith 
132f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
133f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
134f0b84518SBarry Smith 
1351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunction`, `SNESSetJacobianDomainError()`, `SNESVISetVariableBounds()`,
136ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
1374936397dSBarry Smith @*/
138d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionDomainError(SNES snes)
139d71ae5a4SJacob Faibussowitsch {
1404936397dSBarry Smith   PetscFunctionBegin;
1410700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1425f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates input vector is not in the function domain");
1434936397dSBarry Smith   snes->domainerror = PETSC_TRUE;
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1454936397dSBarry Smith }
1464936397dSBarry Smith 
1476a388c36SPeter Brune /*@
148f6dfbefdSBarry Smith   SNESSetJacobianDomainError - tells `SNES` that the function you provided to `SNESSetJacobian()` at the proposed step. For example there is a negative element transformation.
14907b62357SFande Kong 
150c3339decSBarry Smith   Logically Collective
15107b62357SFande Kong 
1522fe279fdSBarry Smith   Input Parameter:
153f6dfbefdSBarry Smith . snes - the `SNES` context
15407b62357SFande Kong 
15507b62357SFande Kong   Level: advanced
15607b62357SFande Kong 
157ced0f3aeSBarry Smith   Notes:
158ced0f3aeSBarry Smith   If this is called the `SNESSolve()` stops iterating and returns with a `SNESConvergedReason` of `SNES_DIVERGED_FUNCTION_DOMAIN`
159ced0f3aeSBarry Smith 
160ced0f3aeSBarry Smith   You should always call `SNESGetConvergedReason()` after each `SNESSolve()` and verify if the iteration converged (positive result) or diverged (negative result).
161ced0f3aeSBarry Smith 
162f0b84518SBarry Smith   You can direct `SNES` to avoid certain steps by using `SNESVISetVariableBounds()`, `SNESVISetComputeVariableBounds()` or
163f0b84518SBarry Smith   `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`
164f0b84518SBarry Smith 
1651cc06b55SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `SNESSetFunctionDomainError()`, `SNESVISetVariableBounds()`,
166ced0f3aeSBarry Smith           `SNESVISetComputeVariableBounds()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESConvergedReason`, `SNESGetConvergedReason()`
16707b62357SFande Kong @*/
168d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobianDomainError(SNES snes)
169d71ae5a4SJacob Faibussowitsch {
17007b62357SFande Kong   PetscFunctionBegin;
17107b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1725f80ce2aSJacob Faibussowitsch   PetscCheck(!snes->errorifnotconverged, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "User code indicates computeJacobian does not make sense");
17307b62357SFande Kong   snes->jacobiandomainerror = PETSC_TRUE;
1743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17507b62357SFande Kong }
17607b62357SFande Kong 
17707b62357SFande Kong /*@
178f6dfbefdSBarry Smith   SNESSetCheckJacobianDomainError - tells `SNESSolve()` whether to check if the user called `SNESSetJacobianDomainError()` Jacobian domain error after
179*420bcc1bSBarry Smith   each Jacobian evaluation. By default, it checks for the Jacobian domain error in the debug mode, and does not check it in the optimized mode.
180b351a90bSFande Kong 
181c3339decSBarry Smith   Logically Collective
182b351a90bSFande Kong 
183b351a90bSFande Kong   Input Parameters:
18420f4b53cSBarry Smith + snes - the `SNES` context
185f6dfbefdSBarry Smith - flg  - indicates if or not to check Jacobian domain error after each Jacobian evaluation
186b351a90bSFande Kong 
187b351a90bSFande Kong   Level: advanced
188b351a90bSFande Kong 
189f6dfbefdSBarry Smith   Note:
190f6dfbefdSBarry Smith   Checks require one extra parallel synchronization for each Jacobian evaluation
191f6dfbefdSBarry Smith 
1921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `SNESSetFunctionDomainError()`, `SNESGetCheckJacobianDomainError()`
193b351a90bSFande Kong @*/
194d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCheckJacobianDomainError(SNES snes, PetscBool flg)
195d71ae5a4SJacob Faibussowitsch {
196b351a90bSFande Kong   PetscFunctionBegin;
197b351a90bSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
198b351a90bSFande Kong   snes->checkjacdomainerror = flg;
1993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
200b351a90bSFande Kong }
201b351a90bSFande Kong 
202b351a90bSFande Kong /*@
203*420bcc1bSBarry Smith   SNESGetCheckJacobianDomainError - Get an indicator whether or not `SNES` is checking Jacobian domain errors after each Jacobian evaluation.
2048383d7d7SFande Kong 
205c3339decSBarry Smith   Logically Collective
2068383d7d7SFande Kong 
2072fe279fdSBarry Smith   Input Parameter:
208f6dfbefdSBarry Smith . snes - the `SNES` context
2098383d7d7SFande Kong 
2102fe279fdSBarry Smith   Output Parameter:
211*420bcc1bSBarry Smith . flg - `PETSC_FALSE` indicates that it is not checking Jacobian domain errors after each Jacobian evaluation
2128383d7d7SFande Kong 
2138383d7d7SFande Kong   Level: advanced
2148383d7d7SFande Kong 
2151cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunction()`, `SNESSetFunctionDomainError()`, `SNESSetCheckJacobianDomainError()`
2168383d7d7SFande Kong @*/
217d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetCheckJacobianDomainError(SNES snes, PetscBool *flg)
218d71ae5a4SJacob Faibussowitsch {
2198383d7d7SFande Kong   PetscFunctionBegin;
2208383d7d7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2214f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
2228383d7d7SFande Kong   *flg = snes->checkjacdomainerror;
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2248383d7d7SFande Kong }
2258383d7d7SFande Kong 
2268383d7d7SFande Kong /*@
227*420bcc1bSBarry Smith   SNESGetFunctionDomainError - Gets the status of the domain error after a call to `SNESComputeFunction()`
2286a388c36SPeter Brune 
229f6dfbefdSBarry Smith   Logically Collective
2306a388c36SPeter Brune 
2312fe279fdSBarry Smith   Input Parameter:
232f6dfbefdSBarry Smith . snes - the `SNES` context
2336a388c36SPeter Brune 
2342fe279fdSBarry Smith   Output Parameter:
235f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a domain error; `PETSC_FALSE` otherwise.
2366a388c36SPeter Brune 
237f6dfbefdSBarry Smith   Level: developer
2386a388c36SPeter Brune 
2391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`
2406a388c36SPeter Brune @*/
241d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror)
242d71ae5a4SJacob Faibussowitsch {
2436a388c36SPeter Brune   PetscFunctionBegin;
2446a388c36SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2454f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
2466a388c36SPeter Brune   *domainerror = snes->domainerror;
2473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2486a388c36SPeter Brune }
2496a388c36SPeter Brune 
25007b62357SFande Kong /*@
251*420bcc1bSBarry Smith   SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to `SNESComputeJacobian()`
25207b62357SFande Kong 
253c3339decSBarry Smith   Logically Collective
25407b62357SFande Kong 
2552fe279fdSBarry Smith   Input Parameter:
256f6dfbefdSBarry Smith . snes - the `SNES` context
25707b62357SFande Kong 
2582fe279fdSBarry Smith   Output Parameter:
259f6dfbefdSBarry Smith . domainerror - Set to `PETSC_TRUE` if there's a Jacobian domain error; `PETSC_FALSE` otherwise.
26007b62357SFande Kong 
26107b62357SFande Kong   Level: advanced
26207b62357SFande Kong 
2631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunctionDomainError()`, `SNESComputeFunction()`, `SNESGetFunctionDomainError()`
26407b62357SFande Kong @*/
265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror)
266d71ae5a4SJacob Faibussowitsch {
26707b62357SFande Kong   PetscFunctionBegin;
26807b62357SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2694f572ea9SToby Isaac   PetscAssertPointer(domainerror, 2);
27007b62357SFande Kong   *domainerror = snes->jacobiandomainerror;
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27207b62357SFande Kong }
27307b62357SFande Kong 
27455849f57SBarry Smith /*@C
275f6dfbefdSBarry Smith   SNESLoad - Loads a `SNES` that has been stored in `PETSCVIEWERBINARY` with `SNESView()`.
27655849f57SBarry Smith 
277c3339decSBarry Smith   Collective
27855849f57SBarry Smith 
27955849f57SBarry Smith   Input Parameters:
280e4094ef1SJacob Faibussowitsch + snes   - the newly loaded `SNES`, this needs to have been created with `SNESCreate()` or
281f6dfbefdSBarry Smith            some related function before a call to `SNESLoad()`.
282f6dfbefdSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()`
28355849f57SBarry Smith 
28455849f57SBarry Smith   Level: intermediate
28555849f57SBarry Smith 
286f6dfbefdSBarry Smith   Note:
287*420bcc1bSBarry Smith   The `SNESType` is determined by the data in the file, any type set into the `SNES` before this call is ignored.
28855849f57SBarry Smith 
2891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `PetscViewer`, `SNESCreate()`, `SNESType`, `PetscViewerBinaryOpen()`, `SNESView()`, `MatLoad()`, `VecLoad()`
29055849f57SBarry Smith @*/
291d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer)
292d71ae5a4SJacob Faibussowitsch {
29355849f57SBarry Smith   PetscBool isbinary;
294060da220SMatthew G. Knepley   PetscInt  classid;
29555849f57SBarry Smith   char      type[256];
29655849f57SBarry Smith   KSP       ksp;
2972d53ad75SBarry Smith   DM        dm;
2982d53ad75SBarry Smith   DMSNES    dmsnes;
29955849f57SBarry Smith 
30055849f57SBarry Smith   PetscFunctionBegin;
3012d53ad75SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
30255849f57SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
3045f80ce2aSJacob Faibussowitsch   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
30555849f57SBarry Smith 
3069566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
3075f80ce2aSJacob Faibussowitsch   PetscCheck(classid == SNES_FILE_CLASSID, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Not SNES next in file");
3089566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
3099566063dSJacob Faibussowitsch   PetscCall(SNESSetType(snes, type));
310dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, load, viewer);
3119566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3129566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &dmsnes));
3139566063dSJacob Faibussowitsch   PetscCall(DMSNESLoad(dmsnes, viewer));
3149566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
3159566063dSJacob Faibussowitsch   PetscCall(KSPLoad(ksp, viewer));
3163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31755849f57SBarry Smith }
3186a388c36SPeter Brune 
3199804daf3SBarry Smith #include <petscdraw.h>
320e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
321e04113cfSBarry Smith   #include <petscviewersaws.h>
322bfb97211SBarry Smith #endif
3238404b7f3SBarry Smith 
324fe2efc57SMark /*@C
325dc4c0fb0SBarry Smith   SNESViewFromOptions - View a `SNES` based on values in the options database
326fe2efc57SMark 
327c3339decSBarry Smith   Collective
328fe2efc57SMark 
329fe2efc57SMark   Input Parameters:
330f6dfbefdSBarry Smith + A    - the `SNES` context
331dc4c0fb0SBarry Smith . obj  - Optional object that provides the options prefix for the checks
332736c3998SJose E. Roman - name - command line option
333fe2efc57SMark 
334fe2efc57SMark   Level: intermediate
335f6dfbefdSBarry Smith 
3361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESView`, `PetscObjectViewFromOptions()`, `SNESCreate()`
337fe2efc57SMark @*/
338d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESViewFromOptions(SNES A, PetscObject obj, const char name[])
339d71ae5a4SJacob Faibussowitsch {
340fe2efc57SMark   PetscFunctionBegin;
341fe2efc57SMark   PetscValidHeaderSpecific(A, SNES_CLASSID, 1);
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
3433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
344fe2efc57SMark }
345fe2efc57SMark 
346789d8953SBarry Smith PETSC_EXTERN PetscErrorCode SNESComputeJacobian_DMDA(SNES, Vec, Mat, Mat, void *);
347789d8953SBarry Smith 
3487e2c5f70SBarry Smith /*@C
349dc4c0fb0SBarry Smith   SNESView - Prints or visualizes the `SNES` data structure.
3509b94acceSBarry Smith 
351c3339decSBarry Smith   Collective
352fee21e36SBarry Smith 
353c7afd0dbSLois Curfman McInnes   Input Parameters:
354f6dfbefdSBarry Smith + snes   - the `SNES` context
355f6dfbefdSBarry Smith - viewer - the `PetscViewer`
356c7afd0dbSLois Curfman McInnes 
3579b94acceSBarry Smith   Options Database Key:
358f6dfbefdSBarry Smith . -snes_view - Calls `SNESView()` at end of `SNESSolve()`
3599b94acceSBarry Smith 
360dc4c0fb0SBarry Smith   Level: beginner
361dc4c0fb0SBarry Smith 
3629b94acceSBarry Smith   Notes:
3639b94acceSBarry Smith   The available visualization contexts include
364f6dfbefdSBarry Smith +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
365f6dfbefdSBarry Smith -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
366c8a8ba5cSLois Curfman McInnes   output where only the first processor opens
367c8a8ba5cSLois Curfman McInnes   the file.  All other processors send their
368c8a8ba5cSLois Curfman McInnes   data to the first processor to print.
3699b94acceSBarry Smith 
370052bf0daSPierre Jolivet   The available formats include
371f6dfbefdSBarry Smith +     `PETSC_VIEWER_DEFAULT` - standard output (default)
372f6dfbefdSBarry Smith -     `PETSC_VIEWER_ASCII_INFO_DETAIL` - more verbose output for `SNESNASM`
373052bf0daSPierre Jolivet 
3743e081fefSLois Curfman McInnes   The user can open an alternative visualization context with
375f6dfbefdSBarry Smith   `PetscViewerASCIIOpen()` - output to a specified file.
3769b94acceSBarry Smith 
377f6dfbefdSBarry Smith   In the debugger you can do "call `SNESView`(snes,0)" to display the `SNES` solver. (The same holds for any PETSc object viewer).
378595c91d4SBarry Smith 
3791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLoad()`, `SNESCreate()`, `PetscViewerASCIIOpen()`
3809b94acceSBarry Smith @*/
381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESView(SNES snes, PetscViewer viewer)
382d71ae5a4SJacob Faibussowitsch {
383fa9f3622SBarry Smith   SNESKSPEW     *kctx;
38494b7f48cSBarry Smith   KSP            ksp;
3857f1410a3SPeter Brune   SNESLineSearch linesearch;
38672a02f06SBarry Smith   PetscBool      iascii, isstring, isbinary, isdraw;
3872d53ad75SBarry Smith   DMSNES         dmsnes;
388e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
389536b137fSBarry Smith   PetscBool issaws;
390bfb97211SBarry Smith #endif
3919b94acceSBarry Smith 
3923a40ed3dSBarry Smith   PetscFunctionBegin;
3930700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
39448a46eb9SPierre Jolivet   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &viewer));
3950700a824SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
396c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, viewer, 2);
39774679c65SBarry Smith 
3989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
4009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
4019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
402e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
4039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
404bfb97211SBarry Smith #endif
40532077d6dSBarry Smith   if (iascii) {
406dc0571f2SMatthew G. Knepley     SNESNormSchedule normschedule;
4078404b7f3SBarry Smith     DM               dm;
4088404b7f3SBarry Smith     PetscErrorCode (*cJ)(SNES, Vec, Mat, Mat, void *);
4098404b7f3SBarry Smith     void       *ctx;
410789d8953SBarry Smith     const char *pre = "";
411dc0571f2SMatthew G. Knepley 
4129566063dSJacob Faibussowitsch     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)snes, viewer));
41348a46eb9SPierre Jolivet     if (!snes->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  SNES has not been set up so information may be incomplete\n"));
414e7788613SBarry Smith     if (snes->ops->view) {
4159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
416dbbe0bcdSBarry Smith       PetscUseTypeMethod(snes, view, viewer);
4179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
4180ef38995SBarry Smith     }
41963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
4209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42148a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4239566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4249566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
42548a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4269b94acceSBarry Smith     if (snes->ksp_ewconv) {
427fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4289b94acceSBarry Smith       if (kctx) {
42963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4329b94acceSBarry Smith       }
4339b94acceSBarry Smith     }
434eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
436eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
43763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
438eb1f6c34SBarry Smith     }
439eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
441eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
44263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
443eb1f6c34SBarry Smith     }
4449566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4459566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
446789d8953SBarry Smith     if (snes->mf_operator) {
4479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
448789d8953SBarry Smith       pre = "Preconditioning ";
449789d8953SBarry Smith     }
4508404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4528404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
454789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
455789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
456789d8953SBarry Smith       MatFDColoring fdcoloring;
4579566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
458789d8953SBarry Smith       if (fdcoloring) {
4599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
460789d8953SBarry Smith       } else {
4619566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
462789d8953SBarry Smith       }
463996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4658404b7f3SBarry Smith     }
4660f5bd95cSBarry Smith   } else if (isstring) {
467317d6ea6SBarry Smith     const char *type;
4689566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4699566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
470dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47155849f57SBarry Smith   } else if (isbinary) {
47255849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
47355849f57SBarry Smith     MPI_Comm    comm;
47455849f57SBarry Smith     PetscMPIInt rank;
47555849f57SBarry Smith     char        type[256];
47655849f57SBarry Smith 
4779566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
479dd400576SPatrick Sanan     if (rank == 0) {
4809566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4819566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4829566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48355849f57SBarry Smith     }
484dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
48572a02f06SBarry Smith   } else if (isdraw) {
48672a02f06SBarry Smith     PetscDraw draw;
48772a02f06SBarry Smith     char      str[36];
48889fd9fafSBarry Smith     PetscReal x, y, bottom, h;
48972a02f06SBarry Smith 
4909566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4919566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4929566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4939566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
4949566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
49589fd9fafSBarry Smith     bottom = y - h;
4969566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
497dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
498e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
499536b137fSBarry Smith   } else if (issaws) {
500d45a07a7SBarry Smith     PetscMPIInt rank;
5012657e9d9SBarry Smith     const char *name;
502d45a07a7SBarry Smith 
5039566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
505dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
506d45a07a7SBarry Smith       char dir[1024];
507d45a07a7SBarry Smith 
5089566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5099566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
510792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51148a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5129566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
513792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
514f05ece33SBarry Smith     }
515bfb97211SBarry Smith #endif
51672a02f06SBarry Smith   }
51772a02f06SBarry Smith   if (snes->linesearch) {
5189566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5209566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
52219bcc07fSBarry Smith   }
523efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5259566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5274a0c5b0cSMatthew G Knepley   }
5289566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5299566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5309566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5319566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5322c155ee1SBarry Smith   if (snes->usesksp) {
5339566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5359566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5372c155ee1SBarry Smith   }
53872a02f06SBarry Smith   if (isdraw) {
53972a02f06SBarry Smith     PetscDraw draw;
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5419566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5427f1410a3SPeter Brune   }
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5449b94acceSBarry Smith }
5459b94acceSBarry Smith 
54676b2cf59SMatthew Knepley /*
54776b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
54876b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
54976b2cf59SMatthew Knepley */
55076b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
551a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5526849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55376b2cf59SMatthew Knepley 
554ac226902SBarry Smith /*@C
555f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
55676b2cf59SMatthew Knepley 
55776b2cf59SMatthew Knepley   Not Collective
55876b2cf59SMatthew Knepley 
55976b2cf59SMatthew Knepley   Input Parameter:
56076b2cf59SMatthew Knepley . snescheck - function that checks for options
56176b2cf59SMatthew Knepley 
562*420bcc1bSBarry Smith   Calling sequence of `snescheck`:
563*420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
564*420bcc1bSBarry Smith 
56576b2cf59SMatthew Knepley   Level: developer
56676b2cf59SMatthew Knepley 
5671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
56876b2cf59SMatthew Knepley @*/
569*420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
570d71ae5a4SJacob Faibussowitsch {
57176b2cf59SMatthew Knepley   PetscFunctionBegin;
57263a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57376b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57576b2cf59SMatthew Knepley }
57676b2cf59SMatthew Knepley 
577d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
578d71ae5a4SJacob Faibussowitsch {
579aa3661deSLisandro Dalcin   Mat          J;
580895c21f2SBarry Smith   MatNullSpace nullsp;
581aa3661deSLisandro Dalcin 
582aa3661deSLisandro Dalcin   PetscFunctionBegin;
5830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
584aa3661deSLisandro Dalcin 
58598613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
58698613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5879566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
58898613b67SLisandro Dalcin   }
58998613b67SLisandro Dalcin 
5900fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
591aa3661deSLisandro Dalcin   if (version == 1) {
5929566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5939566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5949566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5951e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
5960fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
5975f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
598570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
599f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
600aa3661deSLisandro Dalcin #else
6012479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
602aa3661deSLisandro Dalcin #endif
6030fdf79fbSJacob Faibussowitsch   }
604aa3661deSLisandro Dalcin 
60501c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
606895c21f2SBarry Smith   if (snes->jacobian) {
6079566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6081baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
609895c21f2SBarry Smith   }
610895c21f2SBarry Smith 
61163a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
612d3462f78SMatthew Knepley   if (hasOperator) {
613aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
614aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6159566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
616aa3661deSLisandro Dalcin   } else {
617aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
61801c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
619b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6209566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
621172a4300SPeter Brune     } else {
622789d8953SBarry Smith       KSP       ksp;
623789d8953SBarry Smith       PC        pc;
624789d8953SBarry Smith       PetscBool match;
625789d8953SBarry Smith 
6269566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
627aa3661deSLisandro Dalcin       /* Force no preconditioner */
6289566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6299566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6302698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
631aa3661deSLisandro Dalcin       if (!match) {
6329566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6339566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
634aa3661deSLisandro Dalcin       }
635aa3661deSLisandro Dalcin     }
636789d8953SBarry Smith   }
6379566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
639aa3661deSLisandro Dalcin }
640aa3661deSLisandro Dalcin 
641d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
642d71ae5a4SJacob Faibussowitsch {
643dfe15315SJed Brown   SNES snes = (SNES)ctx;
6440298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
645dfe15315SJed Brown 
646dfe15315SJed Brown   PetscFunctionBegin;
64716ebb321SJed Brown   if (PetscLogPrintInfo) {
64816ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6499566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6509566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6519566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6529566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65363a3b9bcSJacob 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));
65416ebb321SJed Brown   }
655dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
656dfe15315SJed Brown   else {
6579566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
658dfe15315SJed Brown     Xfine = Xfine_named;
659dfe15315SJed Brown   }
6609566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
661907f5c5aSLawrence Mitchell   if (Inject) {
6629566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
663907f5c5aSLawrence Mitchell   } else {
6649566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6659566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
666907f5c5aSLawrence Mitchell   }
6679566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6689566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
670dfe15315SJed Brown }
671dfe15315SJed Brown 
672d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
673d71ae5a4SJacob Faibussowitsch {
67416ebb321SJed Brown   PetscFunctionBegin;
6759566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67716ebb321SJed Brown }
67816ebb321SJed Brown 
679a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
680a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
681d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
682d71ae5a4SJacob Faibussowitsch {
683caa4e7f2SJed Brown   SNES  snes = (SNES)ctx;
6840298fd71SBarry Smith   Vec   X, Xnamed = NULL;
685dfe15315SJed Brown   DM    dmsave;
6864e269d77SPeter Brune   void *ctxsave;
68725ce1634SJed Brown   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *) = NULL;
688caa4e7f2SJed Brown 
689caa4e7f2SJed Brown   PetscFunctionBegin;
690dfe15315SJed Brown   dmsave = snes->dm;
6919566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
692dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
6939371c9d4SSatish Balay   else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */ PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
694dfe15315SJed Brown     X = Xnamed;
6959566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
6964e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
69748a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
6984e269d77SPeter Brune   }
6994dde8bb0SMatthew G. Knepley   /* Make sure KSP DM has the Jacobian computation routine */
7004dde8bb0SMatthew G. Knepley   {
7014dde8bb0SMatthew G. Knepley     DMSNES sdm;
7024e269d77SPeter Brune 
7039566063dSJacob Faibussowitsch     PetscCall(DMGetDMSNES(snes->dm, &sdm));
70448a46eb9SPierre Jolivet     if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7054dde8bb0SMatthew G. Knepley   }
7062b93b426SMatthew G. Knepley   /* Compute the operators */
7079566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
7082b93b426SMatthew G. Knepley   /* Put the previous context back */
70948a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7104e269d77SPeter Brune 
7119566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
712dfe15315SJed Brown   snes->dm = dmsave;
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
714caa4e7f2SJed Brown }
715caa4e7f2SJed Brown 
7166cab3a1bSJed Brown /*@
717dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7186cab3a1bSJed Brown 
7196cab3a1bSJed Brown   Collective
7206cab3a1bSJed Brown 
7214165533cSJose E. Roman   Input Parameter:
72220f4b53cSBarry Smith . snes - `SNES` object to configure
7236cab3a1bSJed Brown 
7246cab3a1bSJed Brown   Level: developer
7256cab3a1bSJed Brown 
726dc4c0fb0SBarry Smith   Note:
727dc4c0fb0SBarry 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`
728dc4c0fb0SBarry Smith 
7291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7306cab3a1bSJed Brown @*/
731d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
732d71ae5a4SJacob Faibussowitsch {
7336cab3a1bSJed Brown   DM     dm;
734942e3340SBarry Smith   DMSNES sdm;
7356cab3a1bSJed Brown 
7366cab3a1bSJed Brown   PetscFunctionBegin;
7379566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7389566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
73958b371f3SBarry Smith   if (!snes->jacobian && snes->mf) {
7406cab3a1bSJed Brown     Mat   J;
7416cab3a1bSJed Brown     void *functx;
7429566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7439566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7449566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7459566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7469566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7479566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
748caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7496cab3a1bSJed Brown     Mat J, B;
7509566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7519566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7529566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7539566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
75406f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7559566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7569566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7579566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
758caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7591ba9b98eSMatthew G. Knepley     PetscDS   prob;
7606cab3a1bSJed Brown     Mat       J, B;
7611ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7621ba9b98eSMatthew G. Knepley 
7636cab3a1bSJed Brown     J = snes->jacobian;
7649566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7659566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7669566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7679566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7689566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7699566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7709566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7719566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7726cab3a1bSJed Brown   }
773caa4e7f2SJed Brown   {
774caa4e7f2SJed Brown     KSP ksp;
7759566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
7769566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
7779566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
778caa4e7f2SJed Brown   }
7793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7806cab3a1bSJed Brown }
7816cab3a1bSJed Brown 
782d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
783d71ae5a4SJacob Faibussowitsch {
7845e7c47f3SMatthew G. Knepley   PetscInt i;
7855e7c47f3SMatthew G. Knepley 
7865e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
7873ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
7885e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
7895e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
7905e7c47f3SMatthew G. Knepley     PetscDraw             draw;
7915e7c47f3SMatthew G. Knepley     PetscReal             lpause;
7925e7c47f3SMatthew G. Knepley 
7935e7c47f3SMatthew G. Knepley     if (!vf) continue;
7945e7c47f3SMatthew G. Knepley     if (vf->lg) {
7955e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
7965e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
7979566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
7989566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
7999566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8009566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8019566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8025e7c47f3SMatthew G. Knepley     } else {
8035e7c47f3SMatthew G. Knepley       PetscBool isdraw;
8045e7c47f3SMatthew G. Knepley 
8055e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
8065e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
8079566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
8085e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
8099566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
8109566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8119566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8129566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8139566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8145e7c47f3SMatthew G. Knepley     }
8155e7c47f3SMatthew G. Knepley   }
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8175e7c47f3SMatthew G. Knepley }
8185e7c47f3SMatthew G. Knepley 
819fde5950dSBarry Smith /*@C
820fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
821fde5950dSBarry Smith 
822c3339decSBarry Smith   Collective
823fde5950dSBarry Smith 
824fde5950dSBarry Smith   Input Parameters:
825dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
826fde5950dSBarry Smith . name         - the monitor type one is seeking
827fde5950dSBarry Smith . help         - message indicating what monitoring is done
828fde5950dSBarry Smith . manual       - manual page for the monitor
829fde5950dSBarry Smith . monitor      - the monitor function
830f6dfbefdSBarry 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
831fde5950dSBarry Smith 
832*420bcc1bSBarry Smith   Calling sequence of `monitor`:
833*420bcc1bSBarry Smith + snes - the nonlinear solver context
834*420bcc1bSBarry Smith . it   - the current iteration
835*420bcc1bSBarry Smith . r    - the current function norm
836*420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
837*420bcc1bSBarry Smith 
838*420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
839*420bcc1bSBarry Smith + snes - the nonlinear solver context
840*420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
841*420bcc1bSBarry Smith 
842f6dfbefdSBarry Smith   Options Database Key:
843f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
844f6dfbefdSBarry Smith 
845f6dfbefdSBarry Smith   Level: advanced
846fde5950dSBarry Smith 
8471cc06b55SBarry Smith .seealso: [](ch_snes), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
848db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
849e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
850db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
851c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
852db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
853db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
854fde5950dSBarry Smith @*/
855*420bcc1bSBarry Smith PetscErrorCode SNESMonitorSetFromOptions(SNES snes, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(SNES snes, PetscInt it, PetscReal r, PetscViewerAndFormat *vf), PetscErrorCode (*monitorsetup)(SNES snes, PetscViewerAndFormat *vf))
856d71ae5a4SJacob Faibussowitsch {
857fde5950dSBarry Smith   PetscViewer       viewer;
858fde5950dSBarry Smith   PetscViewerFormat format;
859fde5950dSBarry Smith   PetscBool         flg;
860fde5950dSBarry Smith 
861fde5950dSBarry Smith   PetscFunctionBegin;
8629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
863fde5950dSBarry Smith   if (flg) {
864d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8659566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
8669566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
8671baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8689566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
869fde5950dSBarry Smith   }
8703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
871fde5950dSBarry Smith }
872fde5950dSBarry Smith 
873a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
874d71ae5a4SJacob Faibussowitsch {
875a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
876a4598233SStefano Zampini 
8770f0abf79SStefano Zampini   PetscFunctionBegin;
8780f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
879a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
880a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
881a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
882a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
883a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
884a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
8850f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
886a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
8870f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8880f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8890f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8900f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8910f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8920f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8930f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8940f0abf79SStefano Zampini   PetscOptionsEnd();
8953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8960f0abf79SStefano Zampini }
8970f0abf79SStefano Zampini 
8989b94acceSBarry Smith /*@
899f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9009b94acceSBarry Smith 
901c3339decSBarry Smith   Collective
902c7afd0dbSLois Curfman McInnes 
9039b94acceSBarry Smith   Input Parameter:
904f6dfbefdSBarry Smith . snes - the `SNES` context
9059b94acceSBarry Smith 
90636851e7fSLois Curfman McInnes   Options Database Keys:
907f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
908ceaaa498SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
90970441072SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
910b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
911e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
912ceaaa498SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
913b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
914b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
9154839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
916ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
917a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9183d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
919e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9203d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
9214a221d59SStefano Zampini . -snes_tr_tol <trtol>                                                         - trust region tolerance
922ceaaa498SBarry Smith . -snes_convergence_test <default,skip,correct_pressure>                       - convergence test in nonlinear solver. default `SNESConvergedDefault()`. skip `SNESConvergedSkip()` means continue iterating until max_it or some other criterion is reached, saving expense of convergence test. correct_pressure `SNESConvergedCorrectPressure()` has special handling of a pressure null space.
923fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
924fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
925fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
926fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9274619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
928459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9295e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
930e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
931e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
932ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
933b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
934ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
935e62ac41dSBarry 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.
936e62ac41dSBarry 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.
93782738288SBarry Smith 
938f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
939fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9404b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
94136851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
94236851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
94336851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
94436851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
94536851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
94636851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
94782738288SBarry Smith 
948dc4c0fb0SBarry Smith   Level: beginner
949dc4c0fb0SBarry Smith 
95011ca99fdSLois Curfman McInnes   Notes:
951ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
952ec5066bdSBarry Smith 
953*420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
954*420bcc1bSBarry Smith   and computing explicitly with
955f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
95683e2fdc7SBarry Smith 
957*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9589b94acceSBarry Smith @*/
959d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
960d71ae5a4SJacob Faibussowitsch {
9618afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
962d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
96304d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
964649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
96585385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9660f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
967c40d0f55SPeter Brune   PCSide      pcside;
968a64e098fSPeter Brune   const char *optionsprefix;
9699b94acceSBarry Smith 
9703a40ed3dSBarry Smith   PetscFunctionBegin;
9710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9729566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
973d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
974639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
976d64ed03dSBarry Smith   if (flg) {
9779566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9787adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9799566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
980d64ed03dSBarry Smith   }
9819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
9829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
983186905e3SBarry Smith 
9849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
9859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
9869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
9879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
9889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
9899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
9909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
9919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
9929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
99385385478SLisandro Dalcin 
9949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
995a8054027SBarry Smith   if (flg) {
9965f80ce2aSJacob 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");
9979566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
998a8054027SBarry Smith   }
9999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10001baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1002e35cf81dSBarry Smith   if (flg) {
10035f80ce2aSJacob 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");
10049566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1005e35cf81dSBarry Smith   }
10069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10071baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
100837ec4e1aSPeter Brune 
10099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10101baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1011a8054027SBarry Smith 
1012400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
101385385478SLisandro Dalcin   if (flg) {
101485385478SLisandro Dalcin     switch (indx) {
1015d71ae5a4SJacob Faibussowitsch     case 0:
1016d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1017d71ae5a4SJacob Faibussowitsch       break;
1018d71ae5a4SJacob Faibussowitsch     case 1:
1019d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1020d71ae5a4SJacob Faibussowitsch       break;
1021d71ae5a4SJacob Faibussowitsch     case 2:
1022d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1023d71ae5a4SJacob Faibussowitsch       break;
102485385478SLisandro Dalcin     }
102585385478SLisandro Dalcin   }
102685385478SLisandro Dalcin 
10279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10289566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1029fdacfa88SPeter Brune 
10309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10319566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1032186905e3SBarry Smith 
103385385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
103485385478SLisandro Dalcin 
10359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1036186905e3SBarry Smith 
10370f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10380f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1039a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1040186905e3SBarry Smith 
104190d69ab7SBarry Smith   flg = PETSC_FALSE;
10429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10439566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1044eabae89aSBarry Smith 
10459566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10469566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10479566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1048eabae89aSBarry Smith 
10499566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10509566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10519566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10529566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10539566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10549566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10559566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10572db13446SMatthew G. Knepley 
10589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10599566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10605180491cSLisandro Dalcin 
106190d69ab7SBarry Smith   flg = PETSC_FALSE;
10629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1063459f5d12SBarry Smith   if (flg) {
1064459f5d12SBarry Smith     PetscViewer ctx;
1065e24b481bSBarry Smith 
10669566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10679566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1068459f5d12SBarry Smith   }
10692e7541e6SPeter Brune 
107090d69ab7SBarry Smith   flg = PETSC_FALSE;
10719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10729566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1073c4421ceaSFande Kong 
1074c4421ceaSFande Kong   flg = PETSC_FALSE;
10759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10764b27c08aSLois Curfman McInnes   if (flg) {
10776cab3a1bSJed Brown     void *functx;
1078b1f624c7SBarry Smith     DM    dm;
10799566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1080800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10819566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10829566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10839566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
10849b94acceSBarry Smith   }
1085639f9d9dSBarry Smith 
108644848bc4SPeter Brune   flg = PETSC_FALSE;
10879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
10881baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
108997584545SPeter Brune 
109097584545SPeter Brune   flg = PETSC_FALSE;
10919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
109244848bc4SPeter Brune   if (flg) {
1093c52e227fSPeter Brune     DM dm;
10949566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1095800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10969566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
10979566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
109844848bc4SPeter Brune   }
109944848bc4SPeter Brune 
1100aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1102d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1103a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1104d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1105a8248277SBarry Smith   }
1106aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1108d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1110d28543b3SPeter Brune 
1111c40d0f55SPeter Brune   flg = PETSC_FALSE;
11129566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11149566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1115c40d0f55SPeter Brune 
1116e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11178a70d858SHong Zhang   /*
11188a70d858SHong Zhang     Publish convergence information using SAWs
11198a70d858SHong Zhang   */
11208a70d858SHong Zhang   flg = PETSC_FALSE;
11219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11228a70d858SHong Zhang   if (flg) {
11238a70d858SHong Zhang     void *ctx;
11249566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11259566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11268a70d858SHong Zhang   }
11278a70d858SHong Zhang #endif
11288a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1129b90c6cbeSBarry Smith   {
1130b90c6cbeSBarry Smith     PetscBool set;
1131b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11329566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11331baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1134b90c6cbeSBarry Smith   }
1135b90c6cbeSBarry Smith #endif
1136b90c6cbeSBarry Smith 
113748a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
113876b2cf59SMatthew Knepley 
1139dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11405d973c19SBarry Smith 
11415d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1142dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1143d0609cedSBarry Smith   PetscOptionsEnd();
11444bbc92c1SBarry Smith 
1145d8d34be6SBarry Smith   if (snes->linesearch) {
11469566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11479566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1148d8d34be6SBarry Smith   }
11499e764e56SPeter Brune 
11506aa5e7e9SBarry Smith   if (snes->usesksp) {
11519566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11529566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11539566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11546aa5e7e9SBarry Smith   }
11556991f827SBarry Smith 
1156b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11579566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
115948a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11601baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1161b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1163b3cd9a81SMatthew G. Knepley }
1164b3cd9a81SMatthew G. Knepley 
1165b3cd9a81SMatthew G. Knepley /*@
1166*420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1167b3cd9a81SMatthew G. Knepley 
1168c3339decSBarry Smith   Collective
1169b3cd9a81SMatthew G. Knepley 
1170b3cd9a81SMatthew G. Knepley   Input Parameter:
1171f6dfbefdSBarry Smith . snes - the `SNES` context
1172b3cd9a81SMatthew G. Knepley 
1173*420bcc1bSBarry Smith   Level: advanced
1174b3cd9a81SMatthew G. Knepley 
11751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1176b3cd9a81SMatthew G. Knepley @*/
1177d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1178d71ae5a4SJacob Faibussowitsch {
1179b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11809566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11829b94acceSBarry Smith }
11839b94acceSBarry Smith 
1184bb9467b5SJed Brown /*@C
1185d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1186d25893d9SBarry Smith   the nonlinear solvers.
1187d25893d9SBarry Smith 
1188dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1189d25893d9SBarry Smith 
1190d25893d9SBarry Smith   Input Parameters:
1191f6dfbefdSBarry Smith + snes    - the `SNES` context
1192d25893d9SBarry Smith . compute - function to compute the context
1193d25893d9SBarry Smith - destroy - function to destroy the context
1194d25893d9SBarry Smith 
1195*420bcc1bSBarry Smith   Calling sequence of `compute`:
1196*420bcc1bSBarry Smith + snes - the `SNES` context
1197*420bcc1bSBarry Smith - ctx  - context to be computed
1198*420bcc1bSBarry Smith 
1199*420bcc1bSBarry Smith   Calling sequence of `destroy`:
1200*420bcc1bSBarry Smith . ctx - context to be computed by `compute()`
1201*420bcc1bSBarry Smith 
1202d25893d9SBarry Smith   Level: intermediate
1203d25893d9SBarry Smith 
1204f6dfbefdSBarry Smith   Note:
1205f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1206f6dfbefdSBarry Smith 
1207f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1208f6dfbefdSBarry Smith 
120942747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`
1210d25893d9SBarry Smith @*/
1211*420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx))
1212d71ae5a4SJacob Faibussowitsch {
1213d25893d9SBarry Smith   PetscFunctionBegin;
1214d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1215d25893d9SBarry Smith   snes->ops->usercompute = compute;
1216d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
12173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1218d25893d9SBarry Smith }
1219a847f771SSatish Balay 
1220b07ff414SBarry Smith /*@
1221f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12229b94acceSBarry Smith 
1223c3339decSBarry Smith   Logically Collective
1224fee21e36SBarry Smith 
1225c7afd0dbSLois Curfman McInnes   Input Parameters:
1226f6dfbefdSBarry Smith + snes - the `SNES` context
1227c7afd0dbSLois Curfman McInnes - usrP - optional user context
1228c7afd0dbSLois Curfman McInnes 
122936851e7fSLois Curfman McInnes   Level: intermediate
123036851e7fSLois Curfman McInnes 
1231f6dfbefdSBarry Smith   Notes:
1232f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1233f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1234f6dfbefdSBarry Smith 
1235f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1236f6dfbefdSBarry Smith 
1237*420bcc1bSBarry Smith   Fortran Note:
1238dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1239*420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1240daf670e6SBarry Smith 
12411cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12429b94acceSBarry Smith @*/
1243d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1244d71ae5a4SJacob Faibussowitsch {
1245b07ff414SBarry Smith   KSP ksp;
12461b2093e4SBarry Smith 
12473a40ed3dSBarry Smith   PetscFunctionBegin;
12480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12499566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12509566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12519b94acceSBarry Smith   snes->user = usrP;
12523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12539b94acceSBarry Smith }
125474679c65SBarry Smith 
1255b07ff414SBarry Smith /*@
12569b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1257*420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12589b94acceSBarry Smith 
1259c7afd0dbSLois Curfman McInnes   Not Collective
1260c7afd0dbSLois Curfman McInnes 
12619b94acceSBarry Smith   Input Parameter:
1262f6dfbefdSBarry Smith . snes - `SNES` context
12639b94acceSBarry Smith 
12649b94acceSBarry Smith   Output Parameter:
12659b94acceSBarry Smith . usrP - user context
12669b94acceSBarry Smith 
126736851e7fSLois Curfman McInnes   Level: intermediate
126836851e7fSLois Curfman McInnes 
1269*420bcc1bSBarry Smith   Fortran Note:
1270dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1271*420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1272dc4c0fb0SBarry Smith 
1273*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
12749b94acceSBarry Smith @*/
1275d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1276d71ae5a4SJacob Faibussowitsch {
12773a40ed3dSBarry Smith   PetscFunctionBegin;
12780700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1279e71120c6SJed Brown   *(void **)usrP = snes->user;
12803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12819b94acceSBarry Smith }
128274679c65SBarry Smith 
12839b94acceSBarry Smith /*@
1284*420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
12853565c898SBarry Smith 
1286dc4c0fb0SBarry Smith   Logically Collective
12873565c898SBarry Smith 
12883565c898SBarry Smith   Input Parameters:
1289f6dfbefdSBarry Smith + snes        - `SNES` context
1290f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1291f6dfbefdSBarry 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
1292*420bcc1bSBarry Smith    this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
12933565c898SBarry Smith 
1294f6dfbefdSBarry Smith   Options Database Keys:
129501c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1296f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1297ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1298ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
12993565c898SBarry Smith 
13003565c898SBarry Smith   Level: intermediate
13013565c898SBarry Smith 
1302f6dfbefdSBarry Smith   Note:
1303*420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1304*420bcc1bSBarry Smith   and computing explicitly with
1305f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1306ec5066bdSBarry Smith 
1307*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13083565c898SBarry Smith @*/
1309d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1310d71ae5a4SJacob Faibussowitsch {
13113565c898SBarry Smith   PetscFunctionBegin;
13123565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
131388b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
131488b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13154ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13163565c898SBarry Smith   snes->mf_operator = mf_operator;
13173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13183565c898SBarry Smith }
13193565c898SBarry Smith 
13203565c898SBarry Smith /*@
1321dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13223565c898SBarry Smith 
1323*420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13243565c898SBarry Smith 
13253565c898SBarry Smith   Input Parameter:
1326f6dfbefdSBarry Smith . snes - `SNES` context
13273565c898SBarry Smith 
13283565c898SBarry Smith   Output Parameters:
1329f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1330f6dfbefdSBarry 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
13313565c898SBarry Smith 
13323565c898SBarry Smith   Level: intermediate
13333565c898SBarry Smith 
13341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13353565c898SBarry Smith @*/
1336d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1337d71ae5a4SJacob Faibussowitsch {
13383565c898SBarry Smith   PetscFunctionBegin;
13393565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13403565c898SBarry Smith   if (mf) *mf = snes->mf;
13413565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13433565c898SBarry Smith }
13443565c898SBarry Smith 
13453565c898SBarry Smith /*@
1346*420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13479b94acceSBarry Smith 
1348c7afd0dbSLois Curfman McInnes   Not Collective
1349c7afd0dbSLois Curfman McInnes 
13509b94acceSBarry Smith   Input Parameter:
1351f6dfbefdSBarry Smith . snes - `SNES` context
13529b94acceSBarry Smith 
13539b94acceSBarry Smith   Output Parameter:
13549b94acceSBarry Smith . iter - iteration number
13559b94acceSBarry Smith 
1356dc4c0fb0SBarry Smith   Level: intermediate
1357dc4c0fb0SBarry Smith 
1358c8228a4eSBarry Smith   Notes:
1359c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1360c8228a4eSBarry Smith 
1361c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1362f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
136308405cd6SLois Curfman McInnes .vb
136408405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
136508405cd6SLois Curfman McInnes       if (!(it % 2)) {
136608405cd6SLois Curfman McInnes         [compute Jacobian here]
136708405cd6SLois Curfman McInnes       }
136808405cd6SLois Curfman McInnes .ve
1369f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1370f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1371c8228a4eSBarry Smith 
1372f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1373c04deec6SBarry Smith 
1374*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
13759b94acceSBarry Smith @*/
1376d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1377d71ae5a4SJacob Faibussowitsch {
13783a40ed3dSBarry Smith   PetscFunctionBegin;
13790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13804f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
13819b94acceSBarry Smith   *iter = snes->iter;
13823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13839b94acceSBarry Smith }
138474679c65SBarry Smith 
1385360c497dSPeter Brune /*@
1386360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1387360c497dSPeter Brune 
1388360c497dSPeter Brune   Not Collective
1389360c497dSPeter Brune 
1390d8d19677SJose E. Roman   Input Parameters:
1391f6dfbefdSBarry Smith + snes - `SNES` context
1392a2b725a8SWilliam Gropp - iter - iteration number
1393360c497dSPeter Brune 
1394360c497dSPeter Brune   Level: developer
1395360c497dSPeter Brune 
1396*420bcc1bSBarry Smith   Note:
1397*420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1398*420bcc1bSBarry Smith 
13991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1400360c497dSPeter Brune @*/
1401d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1402d71ae5a4SJacob Faibussowitsch {
1403360c497dSPeter Brune   PetscFunctionBegin;
1404360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14059566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1406360c497dSPeter Brune   snes->iter = iter;
14079566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1409360c497dSPeter Brune }
1410360c497dSPeter Brune 
14119b94acceSBarry Smith /*@
1412b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1413*420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14149b94acceSBarry Smith 
1415c7afd0dbSLois Curfman McInnes   Not Collective
1416c7afd0dbSLois Curfman McInnes 
14179b94acceSBarry Smith   Input Parameter:
1418f6dfbefdSBarry Smith . snes - `SNES` context
14199b94acceSBarry Smith 
14209b94acceSBarry Smith   Output Parameter:
14219b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14229b94acceSBarry Smith 
1423dc4c0fb0SBarry Smith   Level: intermediate
1424dc4c0fb0SBarry Smith 
1425f6dfbefdSBarry Smith   Note:
1426f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1427c96a6f78SLois Curfman McInnes 
14281cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1429db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14309b94acceSBarry Smith @*/
1431d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1432d71ae5a4SJacob Faibussowitsch {
14333a40ed3dSBarry Smith   PetscFunctionBegin;
14340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14354f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
143650ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143850ffb88aSMatthew Knepley }
143950ffb88aSMatthew Knepley 
144050ffb88aSMatthew Knepley /*@
1441b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1442*420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
144350ffb88aSMatthew Knepley 
144450ffb88aSMatthew Knepley   Not Collective
144550ffb88aSMatthew Knepley 
144650ffb88aSMatthew Knepley   Input Parameters:
1447f6dfbefdSBarry Smith + snes     - `SNES` context
144850ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps
144950ffb88aSMatthew Knepley 
1450*420bcc1bSBarry Smith   Options Database Key:
1451*420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1452*420bcc1bSBarry Smith 
145350ffb88aSMatthew Knepley   Level: intermediate
145450ffb88aSMatthew Knepley 
1455*420bcc1bSBarry Smith   Developer Note:
1456*420bcc1bSBarry Smith   The options database key is wrong for this function name
1457*420bcc1bSBarry Smith 
14581cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1459db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
146050ffb88aSMatthew Knepley @*/
1461d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1462d71ae5a4SJacob Faibussowitsch {
146350ffb88aSMatthew Knepley   PetscFunctionBegin;
14640700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
146550ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
14663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
146750ffb88aSMatthew Knepley }
146850ffb88aSMatthew Knepley 
146950ffb88aSMatthew Knepley /*@
1470b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1471*420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
147250ffb88aSMatthew Knepley 
147350ffb88aSMatthew Knepley   Not Collective
147450ffb88aSMatthew Knepley 
147550ffb88aSMatthew Knepley   Input Parameter:
147620f4b53cSBarry Smith . snes - `SNES` context
147750ffb88aSMatthew Knepley 
147850ffb88aSMatthew Knepley   Output Parameter:
147950ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
148050ffb88aSMatthew Knepley 
148150ffb88aSMatthew Knepley   Level: intermediate
148250ffb88aSMatthew Knepley 
14831cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1484db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
148550ffb88aSMatthew Knepley @*/
1486d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1487d71ae5a4SJacob Faibussowitsch {
148850ffb88aSMatthew Knepley   PetscFunctionBegin;
14890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14904f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
149150ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
14923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14939b94acceSBarry Smith }
1494a847f771SSatish Balay 
14952541af92SBarry Smith /*@
14962541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1497*420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
14982541af92SBarry Smith 
14992541af92SBarry Smith   Not Collective
15002541af92SBarry Smith 
15012541af92SBarry Smith   Input Parameter:
1502f6dfbefdSBarry Smith . snes - `SNES` context
15032541af92SBarry Smith 
15042541af92SBarry Smith   Output Parameter:
15052541af92SBarry Smith . nfuncs - number of evaluations
15062541af92SBarry Smith 
15072541af92SBarry Smith   Level: intermediate
15082541af92SBarry Smith 
1509f6dfbefdSBarry Smith   Note:
1510f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1511971e163fSPeter Brune 
15121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15132541af92SBarry Smith @*/
1514d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1515d71ae5a4SJacob Faibussowitsch {
15162541af92SBarry Smith   PetscFunctionBegin;
15170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15184f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15192541af92SBarry Smith   *nfuncs = snes->nfuncs;
15203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15212541af92SBarry Smith }
15222541af92SBarry Smith 
15233d4c4710SBarry Smith /*@
15243d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1525*420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15263d4c4710SBarry Smith 
15273d4c4710SBarry Smith   Not Collective
15283d4c4710SBarry Smith 
15293d4c4710SBarry Smith   Input Parameter:
1530f6dfbefdSBarry Smith . snes - `SNES` context
15313d4c4710SBarry Smith 
15323d4c4710SBarry Smith   Output Parameter:
15333d4c4710SBarry Smith . nfails - number of failed solves
15343d4c4710SBarry Smith 
1535f6dfbefdSBarry Smith   Options Database Key:
15369d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15379d85da0cSMatthew G. Knepley 
1538f6dfbefdSBarry Smith   Level: intermediate
1539f6dfbefdSBarry Smith 
1540f6dfbefdSBarry Smith   Note:
1541f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15423d4c4710SBarry Smith 
15431cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15443d4c4710SBarry Smith @*/
1545d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1546d71ae5a4SJacob Faibussowitsch {
15473d4c4710SBarry Smith   PetscFunctionBegin;
15480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15494f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15503d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15523d4c4710SBarry Smith }
15533d4c4710SBarry Smith 
15543d4c4710SBarry Smith /*@
15553d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1556f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15573d4c4710SBarry Smith 
1558c3339decSBarry Smith   Logically Collective
15593d4c4710SBarry Smith 
15603d4c4710SBarry Smith   Input Parameters:
1561f6dfbefdSBarry Smith + snes     - `SNES` context
15623d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures
15633d4c4710SBarry Smith 
1564f6dfbefdSBarry Smith   Options Database Key:
15659d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15669d85da0cSMatthew G. Knepley 
1567dc4c0fb0SBarry Smith   Level: intermediate
1568dc4c0fb0SBarry Smith 
1569f6dfbefdSBarry Smith   Note:
1570f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
15713d4c4710SBarry Smith 
1572*420bcc1bSBarry Smith   Developer Note:
1573*420bcc1bSBarry Smith   The options database key is wrong for this function name
1574*420bcc1bSBarry Smith 
15751cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
15763d4c4710SBarry Smith @*/
1577d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1578d71ae5a4SJacob Faibussowitsch {
15793d4c4710SBarry Smith   PetscFunctionBegin;
15800700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1581c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
15823d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
15833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15843d4c4710SBarry Smith }
15853d4c4710SBarry Smith 
15863d4c4710SBarry Smith /*@
15873d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1588f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
15893d4c4710SBarry Smith 
15903d4c4710SBarry Smith   Not Collective
15913d4c4710SBarry Smith 
15923d4c4710SBarry Smith   Input Parameter:
1593f6dfbefdSBarry Smith . snes - `SNES` context
15943d4c4710SBarry Smith 
15953d4c4710SBarry Smith   Output Parameter:
15963d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
15973d4c4710SBarry Smith 
15983d4c4710SBarry Smith   Level: intermediate
15993d4c4710SBarry Smith 
1600f6dfbefdSBarry Smith   Note:
1601f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16023d4c4710SBarry Smith 
16031cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16043d4c4710SBarry Smith @*/
1605d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1606d71ae5a4SJacob Faibussowitsch {
16073d4c4710SBarry Smith   PetscFunctionBegin;
16080700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16094f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16103d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16123d4c4710SBarry Smith }
16133d4c4710SBarry Smith 
1614c96a6f78SLois Curfman McInnes /*@
1615b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1616*420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1617c96a6f78SLois Curfman McInnes 
1618c7afd0dbSLois Curfman McInnes   Not Collective
1619c7afd0dbSLois Curfman McInnes 
1620c96a6f78SLois Curfman McInnes   Input Parameter:
1621f6dfbefdSBarry Smith . snes - `SNES` context
1622c96a6f78SLois Curfman McInnes 
1623c96a6f78SLois Curfman McInnes   Output Parameter:
1624c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1625c96a6f78SLois Curfman McInnes 
1626dc4c0fb0SBarry Smith   Level: intermediate
1627dc4c0fb0SBarry Smith 
1628c96a6f78SLois Curfman McInnes   Notes:
1629f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1630c96a6f78SLois Curfman McInnes 
1631f6dfbefdSBarry 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
1632f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1633010be392SBarry Smith 
16341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1635c96a6f78SLois Curfman McInnes @*/
1636d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1637d71ae5a4SJacob Faibussowitsch {
16383a40ed3dSBarry Smith   PetscFunctionBegin;
16390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16404f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1641c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1643c96a6f78SLois Curfman McInnes }
1644c96a6f78SLois Curfman McInnes 
1645971e163fSPeter Brune /*@
1646971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1647f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1648971e163fSPeter Brune 
1649c3339decSBarry Smith   Logically Collective
1650971e163fSPeter Brune 
1651d8d19677SJose E. Roman   Input Parameters:
1652f6dfbefdSBarry Smith + snes  - `SNES` context
1653f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1654971e163fSPeter Brune 
1655971e163fSPeter Brune   Level: developer
1656971e163fSPeter Brune 
16571cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1658971e163fSPeter Brune @*/
1659d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1660d71ae5a4SJacob Faibussowitsch {
1661971e163fSPeter Brune   PetscFunctionBegin;
1662971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1663971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1664971e163fSPeter Brune   snes->counters_reset = reset;
16653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1666971e163fSPeter Brune }
1667971e163fSPeter Brune 
16682999313aSBarry Smith /*@
1669f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16702999313aSBarry Smith 
1671*420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
16722999313aSBarry Smith 
16732999313aSBarry Smith   Input Parameters:
1674f6dfbefdSBarry Smith + snes - the `SNES` context
1675f6dfbefdSBarry Smith - ksp  - the `KSP` context
16762999313aSBarry Smith 
1677dc4c0fb0SBarry Smith   Level: developer
1678dc4c0fb0SBarry Smith 
16792999313aSBarry Smith   Notes:
1680f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
16812999313aSBarry Smith   so this routine is rarely needed.
16822999313aSBarry Smith 
1683f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1684*420bcc1bSBarry Smith   decreased by one when this is called.
16852999313aSBarry Smith 
168642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
16872999313aSBarry Smith @*/
1688d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1689d71ae5a4SJacob Faibussowitsch {
16902999313aSBarry Smith   PetscFunctionBegin;
16910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16920700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
16932999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
16949566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
16959566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
16962999313aSBarry Smith   snes->ksp = ksp;
16973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16982999313aSBarry Smith }
16992999313aSBarry Smith 
170052baeb72SSatish Balay /*@
1701dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
17029b94acceSBarry Smith 
1703d083f849SBarry Smith   Collective
1704c7afd0dbSLois Curfman McInnes 
1705f6dfbefdSBarry Smith   Input Parameter:
1706906ed7ccSBarry Smith . comm - MPI communicator
17079b94acceSBarry Smith 
17089b94acceSBarry Smith   Output Parameter:
170920f4b53cSBarry Smith . outsnes - the new `SNES` context
17109b94acceSBarry Smith 
1711c7afd0dbSLois Curfman McInnes   Options Database Keys:
1712dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1713dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1714dc4c0fb0SBarry Smith                as set by `SNESSetJacobian()`
1715dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1716c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1717c1f60f51SBarry Smith 
171836851e7fSLois Curfman McInnes   Level: beginner
171936851e7fSLois Curfman McInnes 
172095452b02SPatrick Sanan   Developer Notes:
1721f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1722efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1723f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1724f6dfbefdSBarry Smith   in `SNESView()`.
1725efd4aadfSBarry Smith 
1726f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1727f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1728f6dfbefdSBarry Smith 
1729dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1730efd4aadfSBarry Smith 
1731e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
17329b94acceSBarry Smith @*/
1733d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1734d71ae5a4SJacob Faibussowitsch {
17359b94acceSBarry Smith   SNES       snes;
1736fa9f3622SBarry Smith   SNESKSPEW *kctx;
173737fcc0dbSBarry Smith 
17383a40ed3dSBarry Smith   PetscFunctionBegin;
17394f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
17400298fd71SBarry Smith   *outsnes = NULL;
17419566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17428ba1e511SMatthew Knepley 
17439566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17447adad957SLisandro Dalcin 
17458d359177SBarry Smith   snes->ops->converged       = SNESConvergedDefault;
17462c155ee1SBarry Smith   snes->usesksp              = PETSC_TRUE;
174788976e71SPeter Brune   snes->tolerancesset        = PETSC_FALSE;
17489b94acceSBarry Smith   snes->max_its              = 50;
17499750a799SBarry Smith   snes->max_funcs            = 10000;
17509b94acceSBarry Smith   snes->norm                 = 0.0;
1751c1e67a49SFande Kong   snes->xnorm                = 0.0;
1752c1e67a49SFande Kong   snes->ynorm                = 0.0;
1753365a6726SPeter Brune   snes->normschedule         = SNES_NORM_ALWAYS;
17546c67d002SPeter Brune   snes->functype             = SNES_FUNCTION_DEFAULT;
17558ca48ce9SPierre Jolivet   snes->rtol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
1756b4874afaSBarry Smith   snes->ttol                 = 0.0;
17578ca48ce9SPierre Jolivet   snes->abstol               = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50;
17588ca48ce9SPierre Jolivet   snes->stol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
17598ca48ce9SPierre Jolivet   snes->deltatol             = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12;
1760e37c518bSBarry Smith   snes->divtol               = 1.e4;
1761e37c518bSBarry Smith   snes->rnorm0               = 0;
17629b94acceSBarry Smith   snes->nfuncs               = 0;
176350ffb88aSMatthew Knepley   snes->numFailures          = 0;
176450ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17657a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1766e35cf81dSBarry Smith   snes->lagjacobian          = 1;
176737ec4e1aSPeter Brune   snes->jac_iter             = 0;
176837ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1769a8054027SBarry Smith   snes->lagpreconditioner    = 1;
177037ec4e1aSPeter Brune   snes->pre_iter             = 0;
177137ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1772639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1773c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17749e5d0892SLisandro Dalcin   snes->data                 = NULL;
17754dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1776186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17776f24a144SLois Curfman McInnes   snes->nwork                = 0;
17789e5d0892SLisandro Dalcin   snes->work                 = NULL;
177958c9b817SLisandro Dalcin   snes->nvwork               = 0;
17809e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1781758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1782758f92a0SBarry Smith   snes->conv_hist_max        = 0;
17830298fd71SBarry Smith   snes->conv_hist            = NULL;
17840298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1785758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1786971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1787e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1788184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1789efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1790b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1791c40d0f55SPeter Brune 
1792d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1793d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1794d8f46077SPeter Brune   snes->mf_version  = 1;
1795d8f46077SPeter Brune 
17963d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
17973d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
17983d4c4710SBarry Smith 
1799349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
180076bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1801349187a7SBarry Smith 
18024fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18034fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
18044fc747eaSLawrence Mitchell 
18059b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18064dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1807f5af7f23SKarl Rupp 
18089b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
18099b94acceSBarry Smith   kctx->version     = 2;
18100f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
18119b94acceSBarry Smith                              this was too large for some test cases */
181275567043SBarry Smith   kctx->rtol_last   = 0.0;
18130f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
18149b94acceSBarry Smith   kctx->gamma       = 1.0;
18150f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
181671f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
18170f0abf79SStefano Zampini   kctx->threshold   = 0.1;
181875567043SBarry Smith   kctx->lresid_last = 0.0;
181975567043SBarry Smith   kctx->norm_last   = 0.0;
18209b94acceSBarry Smith 
18210f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
18220f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
18230f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
18240f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
18250f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
18260f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
18270f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
18280f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
18290f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
18300f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
18310f0abf79SStefano Zampini 
18329b94acceSBarry Smith   *outsnes = snes;
18333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18349b94acceSBarry Smith }
18359b94acceSBarry Smith 
183688f0584fSBarry Smith /*MC
1837f6dfbefdSBarry Smith     SNESFunction - Functional form used to convey the nonlinear function to `SNES` in `SNESSetFunction()`
183888f0584fSBarry Smith 
183988f0584fSBarry Smith      Synopsis:
1840411c0326SBarry Smith      #include "petscsnes.h"
1841411c0326SBarry Smith      PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx);
184288f0584fSBarry Smith 
1843c3339decSBarry Smith      Collective
18441843f636SBarry Smith 
184588f0584fSBarry Smith      Input Parameters:
1846f6dfbefdSBarry Smith +     snes - the `SNES` context
184788f0584fSBarry Smith .     x    - state at which to evaluate residual
1848f6dfbefdSBarry Smith -     ctx     - optional user-defined function context, passed in with `SNESSetFunction()`
184988f0584fSBarry Smith 
185088f0584fSBarry Smith      Output Parameter:
185188f0584fSBarry Smith .     f  - vector to put residual (function value)
185288f0584fSBarry Smith 
1853878cb397SSatish Balay    Level: intermediate
1854878cb397SSatish Balay 
18551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESGetFunction()`
185688f0584fSBarry Smith M*/
185788f0584fSBarry Smith 
18589b94acceSBarry Smith /*@C
18599b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1860f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
18619b94acceSBarry Smith   equations.
18629b94acceSBarry Smith 
1863c3339decSBarry Smith   Logically Collective
1864fee21e36SBarry Smith 
1865c7afd0dbSLois Curfman McInnes   Input Parameters:
1866f6dfbefdSBarry Smith + snes - the `SNES` context
1867dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
186820f4b53cSBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunction`
1869c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1870dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
18719b94acceSBarry Smith 
187236851e7fSLois Curfman McInnes   Level: beginner
187336851e7fSLois Curfman McInnes 
18741cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunction`
18759b94acceSBarry Smith @*/
1876d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunction(SNES snes, Vec r, PetscErrorCode (*f)(SNES, Vec, Vec, void *), void *ctx)
1877d71ae5a4SJacob Faibussowitsch {
18786cab3a1bSJed Brown   DM dm;
18796cab3a1bSJed Brown 
18803a40ed3dSBarry Smith   PetscFunctionBegin;
18810700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1882d2a683ecSLisandro Dalcin   if (r) {
1883d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1884d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18859566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18869566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
188785385478SLisandro Dalcin     snes->vec_func = r;
1888d2a683ecSLisandro Dalcin   }
18899566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18909566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
189148a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18939b94acceSBarry Smith }
18949b94acceSBarry Smith 
1895e4ed7901SPeter Brune /*@C
18960b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1897e4ed7901SPeter Brune 
1898c3339decSBarry Smith   Logically Collective
1899e4ed7901SPeter Brune 
1900e4ed7901SPeter Brune   Input Parameters:
1901f6dfbefdSBarry Smith + snes - the `SNES` context
1902e4ed7901SPeter Brune - f    - vector to store function value
1903e4ed7901SPeter Brune 
1904dc4c0fb0SBarry Smith   Level: developer
1905dc4c0fb0SBarry Smith 
1906e4ed7901SPeter Brune   Notes:
1907e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1908e4ed7901SPeter Brune 
1909f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1910e4ed7901SPeter Brune 
19111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1912e4ed7901SPeter Brune @*/
1913d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1914d71ae5a4SJacob Faibussowitsch {
1915e4ed7901SPeter Brune   Vec vec_func;
1916e4ed7901SPeter Brune 
1917e4ed7901SPeter Brune   PetscFunctionBegin;
1918e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1919e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1920e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1921efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1922902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19233ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1924902f982fSPeter Brune   }
19259566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19269566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1927f5af7f23SKarl Rupp 
1928217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1930e4ed7901SPeter Brune }
1931e4ed7901SPeter Brune 
1932534ebe21SPeter Brune /*@
1933f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1934f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1935534ebe21SPeter Brune 
1936c3339decSBarry Smith   Logically Collective
1937534ebe21SPeter Brune 
1938534ebe21SPeter Brune   Input Parameters:
1939f6dfbefdSBarry Smith + snes         - the `SNES` context
1940365a6726SPeter Brune - normschedule - the frequency of norm computation
1941534ebe21SPeter Brune 
1942517f1916SMatthew G. Knepley   Options Database Key:
194367b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1944517f1916SMatthew G. Knepley 
1945dc4c0fb0SBarry Smith   Level: advanced
1946dc4c0fb0SBarry Smith 
1947534ebe21SPeter Brune   Notes:
1948f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1949534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
1950534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1951f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1952534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
1953534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
1954534ebe21SPeter Brune   their solution.
1955534ebe21SPeter Brune 
1956e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
1957534ebe21SPeter Brune @*/
1958d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1959d71ae5a4SJacob Faibussowitsch {
1960534ebe21SPeter Brune   PetscFunctionBegin;
1961534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1962365a6726SPeter Brune   snes->normschedule = normschedule;
19633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1964534ebe21SPeter Brune }
1965534ebe21SPeter Brune 
1966534ebe21SPeter Brune /*@
1967f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1968f6dfbefdSBarry Smith   of the `SNES` method.
1969534ebe21SPeter Brune 
1970c3339decSBarry Smith   Logically Collective
1971534ebe21SPeter Brune 
1972534ebe21SPeter Brune   Input Parameters:
1973f6dfbefdSBarry Smith + snes         - the `SNES` context
1974365a6726SPeter Brune - normschedule - the type of the norm used
1975534ebe21SPeter Brune 
1976534ebe21SPeter Brune   Level: advanced
1977534ebe21SPeter Brune 
19781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1979534ebe21SPeter Brune @*/
1980d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1981d71ae5a4SJacob Faibussowitsch {
1982534ebe21SPeter Brune   PetscFunctionBegin;
1983534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1984365a6726SPeter Brune   *normschedule = snes->normschedule;
19853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1986534ebe21SPeter Brune }
1987534ebe21SPeter Brune 
1988c5ce4427SMatthew G. Knepley /*@
1989c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1990c5ce4427SMatthew G. Knepley 
1991c3339decSBarry Smith   Logically Collective
1992c5ce4427SMatthew G. Knepley 
1993c5ce4427SMatthew G. Knepley   Input Parameters:
1994f6dfbefdSBarry Smith + snes - the `SNES` context
1995f6dfbefdSBarry Smith - norm - the value of the norm
1996c5ce4427SMatthew G. Knepley 
1997c5ce4427SMatthew G. Knepley   Level: developer
1998c5ce4427SMatthew G. Knepley 
19991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2000c5ce4427SMatthew G. Knepley @*/
2001d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2002d71ae5a4SJacob Faibussowitsch {
2003c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2004c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2005c5ce4427SMatthew G. Knepley   snes->norm = norm;
20063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2007c5ce4427SMatthew G. Knepley }
2008c5ce4427SMatthew G. Knepley 
2009c5ce4427SMatthew G. Knepley /*@
2010c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2011c5ce4427SMatthew G. Knepley 
2012c5ce4427SMatthew G. Knepley   Not Collective
2013c5ce4427SMatthew G. Knepley 
2014c5ce4427SMatthew G. Knepley   Input Parameter:
2015f6dfbefdSBarry Smith . snes - the `SNES` context
2016c5ce4427SMatthew G. Knepley 
2017c5ce4427SMatthew G. Knepley   Output Parameter:
2018c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2019c5ce4427SMatthew G. Knepley 
2020c5ce4427SMatthew G. Knepley   Level: developer
2021c5ce4427SMatthew G. Knepley 
20221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2023c5ce4427SMatthew G. Knepley @*/
2024d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2025d71ae5a4SJacob Faibussowitsch {
2026c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2027c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20284f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2029c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2031c5ce4427SMatthew G. Knepley }
2032c5ce4427SMatthew G. Knepley 
2033c1e67a49SFande Kong /*@
2034f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2035c1e67a49SFande Kong 
2036c1e67a49SFande Kong   Not Collective
2037c1e67a49SFande Kong 
2038c1e67a49SFande Kong   Input Parameter:
2039f6dfbefdSBarry Smith . snes - the `SNES` context
2040c1e67a49SFande Kong 
2041c1e67a49SFande Kong   Output Parameter:
2042c1e67a49SFande Kong . ynorm - the last computed update norm
2043c1e67a49SFande Kong 
2044c1e67a49SFande Kong   Level: developer
2045c1e67a49SFande Kong 
2046f6dfbefdSBarry Smith   Note:
2047f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2048f6dfbefdSBarry Smith 
20491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2050c1e67a49SFande Kong @*/
2051d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2052d71ae5a4SJacob Faibussowitsch {
2053c1e67a49SFande Kong   PetscFunctionBegin;
2054c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20554f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2056c1e67a49SFande Kong   *ynorm = snes->ynorm;
20573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2058c1e67a49SFande Kong }
2059c1e67a49SFande Kong 
2060c1e67a49SFande Kong /*@
20614591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2062c1e67a49SFande Kong 
2063c1e67a49SFande Kong   Not Collective
2064c1e67a49SFande Kong 
2065c1e67a49SFande Kong   Input Parameter:
2066f6dfbefdSBarry Smith . snes - the `SNES` context
2067c1e67a49SFande Kong 
2068c1e67a49SFande Kong   Output Parameter:
2069c1e67a49SFande Kong . xnorm - the last computed solution norm
2070c1e67a49SFande Kong 
2071c1e67a49SFande Kong   Level: developer
2072c1e67a49SFande Kong 
20731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2074c1e67a49SFande Kong @*/
2075d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2076d71ae5a4SJacob Faibussowitsch {
2077c1e67a49SFande Kong   PetscFunctionBegin;
2078c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20794f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2080c1e67a49SFande Kong   *xnorm = snes->xnorm;
20813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2082c1e67a49SFande Kong }
2083c1e67a49SFande Kong 
208447073ea2SPeter Brune /*@C
2085f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2086f6dfbefdSBarry Smith   of the `SNES` method.
208747073ea2SPeter Brune 
2088c3339decSBarry Smith   Logically Collective
208947073ea2SPeter Brune 
209047073ea2SPeter Brune   Input Parameters:
2091f6dfbefdSBarry Smith + snes - the `SNES` context
2092f6dfbefdSBarry Smith - type - the function type
209347073ea2SPeter Brune 
209447073ea2SPeter Brune   Level: developer
209547073ea2SPeter Brune 
2096*420bcc1bSBarry Smith   Values of the function type\:
2097f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT` - the default for the given `SNESType`
2098f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2099f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED` - a transformation of the function provided with `SNESSetFunction()`
2100f6dfbefdSBarry Smith 
2101*420bcc1bSBarry Smith   Note:
2102f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2103f6dfbefdSBarry Smith 
21041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
210547073ea2SPeter Brune @*/
2106d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2107d71ae5a4SJacob Faibussowitsch {
210847073ea2SPeter Brune   PetscFunctionBegin;
210947073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
211047073ea2SPeter Brune   snes->functype = type;
21113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
211247073ea2SPeter Brune }
211347073ea2SPeter Brune 
211447073ea2SPeter Brune /*@C
2115f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
211647073ea2SPeter Brune   of the SNES method.
211747073ea2SPeter Brune 
2118c3339decSBarry Smith   Logically Collective
211947073ea2SPeter Brune 
212047073ea2SPeter Brune   Input Parameters:
2121f6dfbefdSBarry Smith + snes - the `SNES` context
2122f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
212347073ea2SPeter Brune 
212447073ea2SPeter Brune   Level: advanced
212547073ea2SPeter Brune 
21261cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
212747073ea2SPeter Brune @*/
2128d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2129d71ae5a4SJacob Faibussowitsch {
213047073ea2SPeter Brune   PetscFunctionBegin;
213147073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
213247073ea2SPeter Brune   *type = snes->functype;
21333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2134534ebe21SPeter Brune }
2135534ebe21SPeter Brune 
2136c79ef259SPeter Brune /*@C
2137be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2138c79ef259SPeter Brune   use with composed nonlinear solvers.
2139c79ef259SPeter Brune 
2140c79ef259SPeter Brune   Input Parameters:
2141dc4c0fb0SBarry Smith + snes - the `SNES` context
214237fdd005SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel
2143c79ef259SPeter Brune - ctx  - [optional] user-defined context for private data for the
2144dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2145c79ef259SPeter Brune 
214620f4b53cSBarry Smith   Calling sequence of `f`:
2147f6dfbefdSBarry Smith + snes - the `SNES` context
2148f6dfbefdSBarry Smith . X    - the current solution
2149dc4c0fb0SBarry Smith . B    - the right hand side vector (which may be `NULL`)
2150f6dfbefdSBarry Smith - ctx  - a user provided context
2151f6dfbefdSBarry Smith 
2152dc4c0fb0SBarry Smith   Level: intermediate
2153dc4c0fb0SBarry Smith 
2154f6dfbefdSBarry Smith   Note:
2155f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2156f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2157c79ef259SPeter Brune 
21581cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`
2159c79ef259SPeter Brune @*/
21600b4db180SJacob Faibussowitsch PetscErrorCode SNESSetNGS(SNES snes, PetscErrorCode (*f)(SNES snes, Vec X, Vec B, void *ctx), void *ctx)
2161d71ae5a4SJacob Faibussowitsch {
21626cab3a1bSJed Brown   DM dm;
21636cab3a1bSJed Brown 
2164646217ecSPeter Brune   PetscFunctionBegin;
21656cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21669566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21679566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2169646217ecSPeter Brune }
2170646217ecSPeter Brune 
2171bbc1464cSBarry Smith /*
2172bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2173bbc1464cSBarry Smith    changed during the KSPSolve()
2174bbc1464cSBarry Smith */
2175d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2176d71ae5a4SJacob Faibussowitsch {
2177bbc1464cSBarry Smith   DM     dm;
2178bbc1464cSBarry Smith   DMSNES sdm;
2179bbc1464cSBarry Smith 
2180bbc1464cSBarry Smith   PetscFunctionBegin;
21819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21829566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2183bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2184bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2185792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21869566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21870df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2188ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2189792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21909566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2191bbc1464cSBarry Smith   } else {
2192792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21939566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2194bbc1464cSBarry Smith   }
21953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2196bbc1464cSBarry Smith }
2197bbc1464cSBarry Smith 
2198d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2199d71ae5a4SJacob Faibussowitsch {
2200e03ab78fSPeter Brune   DM     dm;
2201942e3340SBarry Smith   DMSNES sdm;
22026cab3a1bSJed Brown 
22038b0a5094SBarry Smith   PetscFunctionBegin;
22049566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22059566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22068b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2207bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2208792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22099566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2210792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22119566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2212bbc1464cSBarry Smith   } else {
2213792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22149566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2215bbc1464cSBarry Smith   }
22163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22178b0a5094SBarry Smith }
22188b0a5094SBarry Smith 
2219d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2220d71ae5a4SJacob Faibussowitsch {
22218b0a5094SBarry Smith   PetscFunctionBegin;
2222e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2223bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22249566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22259566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22278b0a5094SBarry Smith }
22288b0a5094SBarry Smith 
22298b0a5094SBarry Smith /*@C
2230f6dfbefdSBarry Smith   SNESSetPicard - Use `SNES` to solve the system A(x) x = bp(x) + b via a Picard type iteration (Picard linearization)
22318b0a5094SBarry Smith 
2232c3339decSBarry Smith   Logically Collective
22338b0a5094SBarry Smith 
22348b0a5094SBarry Smith   Input Parameters:
2235f6dfbefdSBarry Smith + snes - the `SNES` context
2236dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
2237*420bcc1bSBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESJacobianFunction`
22386b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2239dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
2240*420bcc1bSBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFunction`
2241dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2242dc4c0fb0SBarry Smith 
2243dc4c0fb0SBarry Smith   Level: intermediate
22448b0a5094SBarry Smith 
22458b0a5094SBarry Smith   Notes:
22466b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2247f450aa47SBarry 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.
2248f450aa47SBarry Smith 
2249f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22508b0a5094SBarry Smith 
2251dc4c0fb0SBarry 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}.
2252dc4c0fb0SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = bp(x^{n}) + b iteration.
22538b0a5094SBarry Smith 
2254dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22558b0a5094SBarry Smith 
22560d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22576b7fb656SBarry Smith   the direct Picard iteration A(x^n) x^{n+1} = bp(x^n) + b
22588b0a5094SBarry Smith 
22598b0a5094SBarry 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
22608b0a5094SBarry 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
22618b0a5094SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-).
22628b0a5094SBarry Smith 
2263dc4c0fb0SBarry 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
2264f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
22656b7fb656SBarry Smith 
2266dc4c0fb0SBarry 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.
22676b7fb656SBarry Smith 
2268dc4c0fb0SBarry 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
22696b7fb656SBarry 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
2270f6dfbefdSBarry 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`.
2271aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2272bbc1464cSBarry Smith 
22731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`, `SNESJacobianFunction`
22748b0a5094SBarry Smith @*/
2275d71ae5a4SJacob 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)
2276d71ae5a4SJacob Faibussowitsch {
2277e03ab78fSPeter Brune   DM dm;
2278e03ab78fSPeter Brune 
22798b0a5094SBarry Smith   PetscFunctionBegin;
22808b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22829566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22839566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22849566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22859566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22878b0a5094SBarry Smith }
22888b0a5094SBarry Smith 
22897971a8bfSPeter Brune /*@C
22907971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
22917971a8bfSPeter Brune 
2292f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
22937971a8bfSPeter Brune 
22947971a8bfSPeter Brune   Input Parameter:
2295f6dfbefdSBarry Smith . snes - the `SNES` context
22967971a8bfSPeter Brune 
2297d8d19677SJose E. Roman   Output Parameters:
2298dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
229920f4b53cSBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunction`
2300dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2301dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
230220f4b53cSBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFunction`
2303dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23047971a8bfSPeter Brune 
23057971a8bfSPeter Brune   Level: advanced
23067971a8bfSPeter Brune 
23071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunction`, `SNESJacobianFunction`
23087971a8bfSPeter Brune @*/
2309d71ae5a4SJacob 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)
2310d71ae5a4SJacob Faibussowitsch {
23117971a8bfSPeter Brune   DM dm;
23127971a8bfSPeter Brune 
23137971a8bfSPeter Brune   PetscFunctionBegin;
23147971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23159566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23169566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23179566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23189566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23207971a8bfSPeter Brune }
23217971a8bfSPeter Brune 
2322d25893d9SBarry Smith /*@C
2323dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2324d25893d9SBarry Smith 
2325c3339decSBarry Smith   Logically Collective
2326d25893d9SBarry Smith 
2327d25893d9SBarry Smith   Input Parameters:
2328f6dfbefdSBarry Smith + snes - the `SNES` context
2329d25893d9SBarry Smith . func - function evaluation routine
2330d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2331dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2332d25893d9SBarry Smith 
233320f4b53cSBarry Smith   Calling sequence of `func`:
233420f4b53cSBarry Smith + snes - the `SNES` solver
233520f4b53cSBarry Smith . x    - vector to put initial guess
2336d25893d9SBarry Smith - ctx  - optional user-defined function context
2337d25893d9SBarry Smith 
2338d25893d9SBarry Smith   Level: intermediate
2339d25893d9SBarry Smith 
2340*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`
2341d25893d9SBarry Smith @*/
23420b4db180SJacob Faibussowitsch PetscErrorCode SNESSetComputeInitialGuess(SNES snes, PetscErrorCode (*func)(SNES snes, Vec x, void *ctx), void *ctx)
2343d71ae5a4SJacob Faibussowitsch {
2344d25893d9SBarry Smith   PetscFunctionBegin;
2345d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2346d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2347d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2349d25893d9SBarry Smith }
2350d25893d9SBarry Smith 
23511096aae1SMatthew Knepley /*@C
2352dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
23531096aae1SMatthew Knepley   it assumes a zero right hand side.
23541096aae1SMatthew Knepley 
2355c3339decSBarry Smith   Logically Collective
23561096aae1SMatthew Knepley 
23571096aae1SMatthew Knepley   Input Parameter:
2358f6dfbefdSBarry Smith . snes - the `SNES` context
23591096aae1SMatthew Knepley 
23601096aae1SMatthew Knepley   Output Parameter:
2361*420bcc1bSBarry Smith . rhs - the right hand side vector or `NULL` if there is no right-hand side vector
23621096aae1SMatthew Knepley 
23631096aae1SMatthew Knepley   Level: intermediate
23641096aae1SMatthew Knepley 
23651cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23661096aae1SMatthew Knepley @*/
2367d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2368d71ae5a4SJacob Faibussowitsch {
23691096aae1SMatthew Knepley   PetscFunctionBegin;
23700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23714f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
237285385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23741096aae1SMatthew Knepley }
23751096aae1SMatthew Knepley 
23769b94acceSBarry Smith /*@
2377f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23789b94acceSBarry Smith 
2379c3339decSBarry Smith   Collective
2380c7afd0dbSLois Curfman McInnes 
23819b94acceSBarry Smith   Input Parameters:
2382f6dfbefdSBarry Smith + snes - the `SNES` context
2383c7afd0dbSLois Curfman McInnes - x    - input vector
23849b94acceSBarry Smith 
23859b94acceSBarry Smith   Output Parameter:
2386f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
23879b94acceSBarry Smith 
2388dc4c0fb0SBarry Smith   Level: developer
2389dc4c0fb0SBarry Smith 
2390f6dfbefdSBarry Smith   Note:
2391f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2392bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
239336851e7fSLois Curfman McInnes 
23941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
23959b94acceSBarry Smith @*/
2396d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2397d71ae5a4SJacob Faibussowitsch {
23986cab3a1bSJed Brown   DM     dm;
2399942e3340SBarry Smith   DMSNES sdm;
24009b94acceSBarry Smith 
24013a40ed3dSBarry Smith   PetscFunctionBegin;
24020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24030700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24040700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2405c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2406c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2407e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2408184914b5SBarry Smith 
24099566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24109566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24110fdf79fbSJacob 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().");
241232f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
241348a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24149566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24158ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24168ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2417800f99ffSJeremy L Thompson     {
2418800f99ffSJeremy L Thompson       void *ctx;
2419800f99ffSJeremy L Thompson       PetscErrorCode (*computefunction)(SNES, Vec, Vec, void *);
2420800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2421800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2422800f99ffSJeremy L Thompson     }
24239566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
242448a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24250fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24269566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24270fdf79fbSJacob Faibussowitsch   }
24281baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2429ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2430422a814eSBarry Smith   /*
2431422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2432422a814eSBarry Smith      propagate the value to all processes
2433422a814eSBarry Smith   */
24341baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24369b94acceSBarry Smith }
24379b94acceSBarry Smith 
2438c79ef259SPeter Brune /*@
2439f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2440bbc1464cSBarry Smith 
2441c3339decSBarry Smith   Collective
2442bbc1464cSBarry Smith 
2443bbc1464cSBarry Smith   Input Parameters:
2444f6dfbefdSBarry Smith + snes - the `SNES` context
2445bbc1464cSBarry Smith - x    - input vector
2446bbc1464cSBarry Smith 
2447bbc1464cSBarry Smith   Output Parameter:
2448f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2449bbc1464cSBarry Smith 
2450dc4c0fb0SBarry Smith   Level: developer
2451dc4c0fb0SBarry Smith 
2452bbc1464cSBarry Smith   Notes:
2453*420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2454bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2455bbc1464cSBarry Smith 
2456f6dfbefdSBarry Smith   Since this function is intended for use with finite differencing it does not subtract the right hand side vector provided with `SNESSolve()`
2457f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2458f6dfbefdSBarry 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.
2459bbc1464cSBarry Smith 
24601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2461bbc1464cSBarry Smith @*/
2462d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2463d71ae5a4SJacob Faibussowitsch {
2464bbc1464cSBarry Smith   DM     dm;
2465bbc1464cSBarry Smith   DMSNES sdm;
2466bbc1464cSBarry Smith 
2467bbc1464cSBarry Smith   PetscFunctionBegin;
2468bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2469bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2470bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2471bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2472bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2473e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2474bbc1464cSBarry Smith 
24759566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24769566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24789566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2479bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2480bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2481792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24829566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2484bbc1464cSBarry Smith   snes->nfuncs++;
2485bbc1464cSBarry Smith   /*
2486bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2487bbc1464cSBarry Smith      propagate the value to all processes
2488bbc1464cSBarry Smith   */
24891baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2491bbc1464cSBarry Smith }
2492bbc1464cSBarry Smith 
2493bbc1464cSBarry Smith /*@
2494f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with  `SNESSetNGS()`.
2495c79ef259SPeter Brune 
2496c3339decSBarry Smith   Collective
2497c79ef259SPeter Brune 
2498c79ef259SPeter Brune   Input Parameters:
2499f6dfbefdSBarry Smith + snes - the `SNES` context
2500c79ef259SPeter Brune . x    - input vector
2501c79ef259SPeter Brune - b    - rhs vector
2502c79ef259SPeter Brune 
2503c79ef259SPeter Brune   Output Parameter:
2504c79ef259SPeter Brune . x - new solution vector
2505c79ef259SPeter Brune 
2506dc4c0fb0SBarry Smith   Level: developer
2507dc4c0fb0SBarry Smith 
2508f6dfbefdSBarry Smith   Note:
2509f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2510c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2511c79ef259SPeter Brune   themselves.
2512c79ef259SPeter Brune 
25131cc06b55SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESSetNGS()`, `SNESComputeFunction()`
2514c79ef259SPeter Brune @*/
2515d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2516d71ae5a4SJacob Faibussowitsch {
25176cab3a1bSJed Brown   DM     dm;
2518942e3340SBarry Smith   DMSNES sdm;
2519646217ecSPeter Brune 
2520646217ecSPeter Brune   PetscFunctionBegin;
2521646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2522064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2523064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2524064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2525064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2526e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25289566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25299566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25300fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25319566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2532792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25339566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2536646217ecSPeter Brune }
2537646217ecSPeter Brune 
2538d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2539d71ae5a4SJacob Faibussowitsch {
254012837594SBarry Smith   Mat               A, B, C, D, jacobian;
2541e885f1abSBarry Smith   Vec               x = snes->vec_sol, f = snes->vec_func;
2542e885f1abSBarry Smith   PetscReal         nrm, gnorm;
254381e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
25440e276705SLisandro Dalcin   MatType           mattype;
2545e885f1abSBarry Smith   PetscInt          m, n, M, N;
2546e885f1abSBarry Smith   void             *functx;
25472cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
25483325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2549e885f1abSBarry Smith   MPI_Comm          comm;
2550e885f1abSBarry Smith   PetscInt          tabs;
255112837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
25523325ff46SBarry Smith   PetscViewerFormat format;
2553e885f1abSBarry Smith 
2554e885f1abSBarry Smith   PetscFunctionBegin;
2555d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
25569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
25579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
25589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
25594ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
25609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
25614ead3382SBarry Smith   /* Cannot remove the what otherwise would be redundant call to (PetscOptionsReal("-snes_test_jacobian_display_threshold") below because its usage is different than the replacement usage */
25629566063dSJacob 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));
2563d0609cedSBarry Smith   PetscOptionsEnd();
25643ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2565e885f1abSBarry Smith 
25669566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
25679566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
25689566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
25699566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
25709566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
257112837594SBarry Smith   if (!complete_print && !directionsprinted) {
25729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
25739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
257412837594SBarry Smith   }
257512837594SBarry Smith   if (!directionsprinted) {
25769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
25779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
257812837594SBarry Smith     directionsprinted = PETSC_TRUE;
2579e885f1abSBarry Smith   }
25801baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2581e885f1abSBarry Smith 
25829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
258312837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
258412837594SBarry Smith   else jacobian = snes->jacobian_pre;
258512837594SBarry Smith 
2586a82339d0SMatthew G. Knepley   if (!x) {
25879566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(jacobian, &x, NULL));
2588a82339d0SMatthew G. Knepley   } else {
25899566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
2590a82339d0SMatthew G. Knepley   }
2591a82339d0SMatthew G. Knepley   if (!f) {
25929566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &f));
2593a82339d0SMatthew G. Knepley   } else {
25949566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)f));
2595a82339d0SMatthew G. Knepley   }
2596a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
25979566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
25989566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
25999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
260012837594SBarry Smith   while (jacobian) {
26012cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
26022cd624f9SStefano Zampini 
26032cd624f9SStefano Zampini     if (istranspose) {
26049566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
26052cd624f9SStefano Zampini       Jsave    = jacobian;
26062cd624f9SStefano Zampini       jacobian = JT;
26072cd624f9SStefano Zampini     }
26089566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
260912837594SBarry Smith     if (flg) {
261012837594SBarry Smith       A = jacobian;
26119566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
261212837594SBarry Smith     } else {
26139566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
261412837594SBarry Smith     }
2615e885f1abSBarry Smith 
26169566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
26179566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
26189566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
26199566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
26209566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
26219566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
26229566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
26239566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
26249566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2625e885f1abSBarry Smith 
26269566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
26279566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
262812837594SBarry Smith 
26299566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
26309566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26319566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
26329566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
26339566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
263412837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
26359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
263612837594SBarry Smith 
2637e885f1abSBarry Smith     if (complete_print) {
26389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
26399566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
26409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
26419566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2642e885f1abSBarry Smith     }
2643e885f1abSBarry Smith 
2644df10fb39SFande Kong     if (threshold_print || complete_print) {
2645e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2646e885f1abSBarry Smith       PetscScalar       *cvals;
2647e885f1abSBarry Smith       const PetscInt    *bcols;
2648e885f1abSBarry Smith       const PetscScalar *bvals;
2649e885f1abSBarry Smith 
26509566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
26519566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
26529566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
26539566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
26549566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
26559566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
26560e276705SLisandro Dalcin 
26579566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
26589566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2659e885f1abSBarry Smith 
2660e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
26619566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
26629566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2663e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
266423a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2665e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2666e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2667e885f1abSBarry Smith             cncols += 1;
2668e885f1abSBarry Smith           }
2669e885f1abSBarry Smith         }
267048a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
26719566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
26729566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2673e885f1abSBarry Smith       }
26749566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
26759566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
26769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
26779566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
26789566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2679e885f1abSBarry Smith     }
26809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
26819566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
26829566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
26832cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
268412837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
268512837594SBarry Smith       jacobian = snes->jacobian_pre;
26869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
26879371c9d4SSatish Balay     } else jacobian = NULL;
268812837594SBarry Smith   }
26899566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
26901baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
26919566063dSJacob Faibussowitsch   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
26929566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
26933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2694e885f1abSBarry Smith }
2695e885f1abSBarry Smith 
269662fef451SLois Curfman McInnes /*@
2697f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
269862fef451SLois Curfman McInnes 
2699c3339decSBarry Smith   Collective
2700c7afd0dbSLois Curfman McInnes 
270162fef451SLois Curfman McInnes   Input Parameters:
2702f6dfbefdSBarry Smith + snes - the `SNES` context
2703e4094ef1SJacob Faibussowitsch - X    - input vector
270462fef451SLois Curfman McInnes 
270562fef451SLois Curfman McInnes   Output Parameters:
2706c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2707*420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2708fee21e36SBarry Smith 
2709e35cf81dSBarry Smith   Options Database Keys:
271067b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
271167b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2712455a5933SJed 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.
2713455a5933SJed 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
2714693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2715693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2716693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
27174c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
271894d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2719a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2720c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2721dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2722dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2723a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2724a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2725c01495d3SJed Brown 
2726dc4c0fb0SBarry Smith   Level: developer
2727dc4c0fb0SBarry Smith 
2728f6dfbefdSBarry Smith   Note:
272962fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
273062fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
273162fef451SLois Curfman McInnes 
2732*420bcc1bSBarry Smith   Developer Note:
2733dc4c0fb0SBarry 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
2734*420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2735e885f1abSBarry Smith 
27361cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
273762fef451SLois Curfman McInnes @*/
2738d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2739d71ae5a4SJacob Faibussowitsch {
2740ace3abfcSBarry Smith   PetscBool flag;
27416cab3a1bSJed Brown   DM        dm;
2742942e3340SBarry Smith   DMSNES    sdm;
2743e0e3a89bSBarry Smith   KSP       ksp;
27443a40ed3dSBarry Smith 
27453a40ed3dSBarry Smith   PetscFunctionBegin;
27460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
27470700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2748c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2749e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
27509566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
27519566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
27523232da50SPeter Brune 
275301c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2754fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2755fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2756f5af7f23SKarl Rupp 
27579566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2758fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
27599566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
27609566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2761ebd3b9afSBarry Smith     if (flag) {
27629566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27639566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2764ebd3b9afSBarry Smith     }
27653ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
276637ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
276763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
27689566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2769ebd3b9afSBarry Smith     if (flag) {
27709566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27719566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2772ebd3b9afSBarry Smith     }
27733ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2774e35cf81dSBarry Smith   }
2775efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
27769566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
27779566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
27783ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2779d728fb7dSPeter Brune   }
2780e35cf81dSBarry Smith 
27819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
27829566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2783800f99ffSJeremy L Thompson   {
2784800f99ffSJeremy L Thompson     void *ctx;
2785800f99ffSJeremy L Thompson     PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *);
2786800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2787800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2788800f99ffSJeremy L Thompson   }
27899566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
27909566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
279128d58a37SPierre Jolivet 
279228d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
27939566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2794a8054027SBarry Smith 
2795e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
27969566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
27973b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
27989566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
27999566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
28003b4f5425SBarry Smith     snes->lagpreconditioner = -1;
28013b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
28029566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
28039566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
280437ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
280563a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
28069566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2807d1e9a80fSBarry Smith   } else {
28089566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
28099566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2810a8054027SBarry Smith   }
2811a8054027SBarry Smith 
28129566063dSJacob Faibussowitsch   PetscCall(SNESTestJacobian(snes));
28136d84be18SBarry Smith   /* make sure user returned a correct Jacobian and preconditioner */
281494ab13aaSBarry Smith   /* PetscValidHeaderSpecific(A,MAT_CLASSID,3);
281594ab13aaSBarry Smith     PetscValidHeaderSpecific(B,MAT_CLASSID,4);   */
2816693365a8SJed Brown   {
2817693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
28189566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
28199566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
28209566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
28219566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2822693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
28230298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2824693365a8SJed Brown       PetscViewer vdraw, vstdout;
28256b3a5b13SJed Brown       PetscBool   flg;
2826693365a8SJed Brown       if (flag_operator) {
28279566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2828693365a8SJed Brown         Bexp = Bexp_mine;
2829693365a8SJed Brown       } else {
2830693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
28319566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
283294ab13aaSBarry Smith         if (flg) Bexp = B;
2833693365a8SJed Brown         else {
2834693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
28359566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2836693365a8SJed Brown           Bexp = Bexp_mine;
2837693365a8SJed Brown         }
2838693365a8SJed Brown       }
28399566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
28409566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
28419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2842693365a8SJed Brown       if (flag_draw || flag_contour) {
28439566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
28449566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28450298fd71SBarry Smith       } else vdraw = NULL;
28469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
28479566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
28489566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
28499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
28509566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
28519566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
28529566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
28539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
28549566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2855693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
28569566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
28579566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
28589566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2859693365a8SJed Brown       }
28609566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
28619566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
28629566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
28639566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2864693365a8SJed Brown     }
2865693365a8SJed Brown   }
28664c30e9fbSJed Brown   {
28676719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
28686719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
28699566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
28709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
28719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
28729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
28739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
287427b0f280SBarry Smith     if (flag_threshold) {
28759566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
28769566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
287727b0f280SBarry Smith     }
28786719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
28794c30e9fbSJed Brown       Mat           Bfd;
28804c30e9fbSJed Brown       PetscViewer   vdraw, vstdout;
2881335efc43SPeter Brune       MatColoring   coloring;
28824c30e9fbSJed Brown       ISColoring    iscoloring;
28834c30e9fbSJed Brown       MatFDColoring matfdcoloring;
28844c30e9fbSJed Brown       PetscErrorCode (*func)(SNES, Vec, Vec, void *);
28854c30e9fbSJed Brown       void     *funcctx;
28866719d8e4SJed Brown       PetscReal norm1, norm2, normmax;
28874c30e9fbSJed Brown 
28889566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
28899566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
28909566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
28919566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
28929566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
28939566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
28949566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
28959566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
28969566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
28979566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
28984c30e9fbSJed Brown 
28994c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
29009566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
29019566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
29029566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
29039566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
29049566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
29059566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
29069566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
29074c30e9fbSJed Brown 
29089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
29094c30e9fbSJed Brown       if (flag_draw || flag_contour) {
29109566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
29119566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29120298fd71SBarry Smith       } else vdraw = NULL;
29139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
29149566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
29159566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
29169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
29179566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29189566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
29199566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
29209566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
29219566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
29229566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
29239566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
29249566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
29254c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
29269566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29279566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
29289566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
29294c30e9fbSJed Brown       }
29309566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29316719d8e4SJed Brown 
29326719d8e4SJed Brown       if (flag_threshold) {
29336719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
29349566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
29359566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
29366719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
29376719d8e4SJed Brown           const PetscScalar *ba, *ca;
29386719d8e4SJed Brown           const PetscInt    *bj, *cj;
29396719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
29406719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
29419566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
29429566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
29435f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
29446719d8e4SJed Brown           for (j = 0; j < bn; j++) {
29456719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
29466719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
29476719d8e4SJed Brown               maxentrycol = bj[j];
29486719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
29496719d8e4SJed Brown             }
29506719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
29516719d8e4SJed Brown               maxdiffcol = bj[j];
29526719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
29536719d8e4SJed Brown             }
29546719d8e4SJed Brown             if (rdiff > maxrdiff) {
29556719d8e4SJed Brown               maxrdiffcol = bj[j];
29566719d8e4SJed Brown               maxrdiff    = rdiff;
29576719d8e4SJed Brown             }
29586719d8e4SJed Brown           }
29596719d8e4SJed Brown           if (maxrdiff > 1) {
296063a3b9bcSJacob 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));
29616719d8e4SJed Brown             for (j = 0; j < bn; j++) {
29626719d8e4SJed Brown               PetscReal rdiff;
29636719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
296448a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
29656719d8e4SJed Brown             }
296663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
29676719d8e4SJed Brown           }
29689566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
29699566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
29706719d8e4SJed Brown         }
29716719d8e4SJed Brown       }
29729566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29739566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
29744c30e9fbSJed Brown     }
29754c30e9fbSJed Brown   }
29763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29779b94acceSBarry Smith }
29789b94acceSBarry Smith 
2979bf388a1fSBarry Smith /*MC
2980*420bcc1bSBarry Smith     SNESJacobianFunction - Functional form used by `SNES` to compute the nonlinear Jacobian of the function to be solved by `SNES`
2981bf388a1fSBarry Smith 
2982bf388a1fSBarry Smith      Synopsis:
2983411c0326SBarry Smith      #include "petscsnes.h"
2984411c0326SBarry Smith      PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx);
2985bf388a1fSBarry Smith 
2986c3339decSBarry Smith      Collective
29871843f636SBarry Smith 
29881843f636SBarry Smith     Input Parameters:
29891843f636SBarry Smith +  x - input vector, the Jacobian is to be computed at this value
2990bf388a1fSBarry Smith -  ctx - [optional] user-defined Jacobian context
2991bf388a1fSBarry Smith 
29921843f636SBarry Smith     Output Parameters:
29931843f636SBarry Smith +  Amat - the matrix that defines the (approximate) Jacobian
2994dc4c0fb0SBarry Smith -  Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
29951843f636SBarry Smith 
2996878cb397SSatish Balay    Level: intermediate
2997878cb397SSatish Balay 
29981cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESSetJacobian()`, `SNESGetJacobian()`
2999bf388a1fSBarry Smith M*/
3000bf388a1fSBarry Smith 
30019b94acceSBarry Smith /*@C
30029b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3003044dda88SLois Curfman McInnes   location to store the matrix.
30049b94acceSBarry Smith 
3005c3339decSBarry Smith   Logically Collective
3006c7afd0dbSLois Curfman McInnes 
30079b94acceSBarry Smith   Input Parameters:
3008f6dfbefdSBarry Smith + snes - the `SNES` context
3009e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3010dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
3011dc4c0fb0SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFunction` for details
3012c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3013dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3014dc4c0fb0SBarry Smith 
3015dc4c0fb0SBarry Smith   Level: beginner
30169b94acceSBarry Smith 
30179b94acceSBarry Smith   Notes:
3018dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
301916913363SBarry Smith   each matrix.
302016913363SBarry Smith 
3021dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3022dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3023895c21f2SBarry Smith 
3024dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3025f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3026a8a26c1eSJed Brown 
3027c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3028f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3029c3cc8fd1SJed Brown 
30301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
3031db781477SPatrick Sanan           `SNESSetPicard()`, `SNESJacobianFunction`
30329b94acceSBarry Smith @*/
3033d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx)
3034d71ae5a4SJacob Faibussowitsch {
30356cab3a1bSJed Brown   DM dm;
30363a7fca6bSBarry Smith 
30373a40ed3dSBarry Smith   PetscFunctionBegin;
30380700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3039e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3040e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3041e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3042e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
30439566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30449566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3045e5d3d808SBarry Smith   if (Amat) {
30469566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
30479566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3048f5af7f23SKarl Rupp 
3049e5d3d808SBarry Smith     snes->jacobian = Amat;
30503a7fca6bSBarry Smith   }
3051e5d3d808SBarry Smith   if (Pmat) {
30529566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
30539566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3054f5af7f23SKarl Rupp 
3055e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
30563a7fca6bSBarry Smith   }
30573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30589b94acceSBarry Smith }
305962fef451SLois Curfman McInnes 
3060c2aafc4cSSatish Balay /*@C
3061b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3062b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3063b4fd4287SBarry Smith 
3064*420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3065c7afd0dbSLois Curfman McInnes 
3066b4fd4287SBarry Smith   Input Parameter:
3067b4fd4287SBarry Smith . snes - the nonlinear solver context
3068b4fd4287SBarry Smith 
3069b4fd4287SBarry Smith   Output Parameters:
3070dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3071dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
307220f4b53cSBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFunction`
3073dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3074fee21e36SBarry Smith 
307536851e7fSLois Curfman McInnes   Level: advanced
307636851e7fSLois Curfman McInnes 
30771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFunction`, `SNESGetFunction()`
3078b4fd4287SBarry Smith @*/
3079d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES, Vec, Mat, Mat, void *), void **ctx)
3080d71ae5a4SJacob Faibussowitsch {
30816cab3a1bSJed Brown   DM dm;
30826cab3a1bSJed Brown 
30833a40ed3dSBarry Smith   PetscFunctionBegin;
30840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3085e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3086e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
30879566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3088800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
30893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3090b4fd4287SBarry Smith }
3091b4fd4287SBarry Smith 
3092d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3093d71ae5a4SJacob Faibussowitsch {
309458b371f3SBarry Smith   DM     dm;
309558b371f3SBarry Smith   DMSNES sdm;
309658b371f3SBarry Smith 
309758b371f3SBarry Smith   PetscFunctionBegin;
30989566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
30999566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
310058b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
310158b371f3SBarry Smith     DM        dm;
310258b371f3SBarry Smith     PetscBool isdense, ismf;
310358b371f3SBarry Smith 
31049566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31059566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
31069566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
310758b371f3SBarry Smith     if (isdense) {
31089566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
310958b371f3SBarry Smith     } else if (!ismf) {
31109566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
311158b371f3SBarry Smith     }
311258b371f3SBarry Smith   }
31133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
311458b371f3SBarry Smith }
311558b371f3SBarry Smith 
31169b94acceSBarry Smith /*@
31179b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3118272ac6f2SLois Curfman McInnes   of a nonlinear solver.
31199b94acceSBarry Smith 
3120c3339decSBarry Smith   Collective
3121fee21e36SBarry Smith 
31222fe279fdSBarry Smith   Input Parameter:
3123f6dfbefdSBarry Smith . snes - the `SNES` context
3124c7afd0dbSLois Curfman McInnes 
3125dc4c0fb0SBarry Smith   Level: advanced
3126dc4c0fb0SBarry Smith 
3127f6dfbefdSBarry Smith   Note:
3128f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3129f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3130f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3131f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3132f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3133272ac6f2SLois Curfman McInnes 
31341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
31359b94acceSBarry Smith @*/
3136d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3137d71ae5a4SJacob Faibussowitsch {
31386cab3a1bSJed Brown   DM             dm;
3139942e3340SBarry Smith   DMSNES         sdm;
3140c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
31416e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
31429b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
31439b5c1c08SStefano Zampini   Vec            f, fpc;
31449b5c1c08SStefano Zampini   void          *funcctx;
31459b5c1c08SStefano Zampini   void          *jacctx, *appctx;
31469b5c1c08SStefano Zampini   Mat            j, jpre;
31476b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
31486b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
31496e2a1849SPeter Brune   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
3150d1e9a80fSBarry Smith   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
31513a40ed3dSBarry Smith 
31523a40ed3dSBarry Smith   PetscFunctionBegin;
31530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
31543ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3155fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
31569b94acceSBarry Smith 
315748a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
315885385478SLisandro Dalcin 
31599566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
316058c9b817SLisandro Dalcin 
31619566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31629566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
31639566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
316458b371f3SBarry Smith 
316548a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3166efd51863SBarry Smith 
316748a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3168b710008aSBarry Smith 
3169d8d34be6SBarry Smith   if (snes->linesearch) {
31709566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
31719566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3172d8d34be6SBarry Smith   }
31739e764e56SPeter Brune 
31749b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3175b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3176172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3177172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3178172a4300SPeter Brune   }
3179d8f46077SPeter Brune 
3180efd4aadfSBarry Smith   if (snes->npc) {
31816e2a1849SPeter Brune     /* copy the DM over */
31829566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31839566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
31846e2a1849SPeter Brune 
31859566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
31869566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
31879566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
31889566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
31899566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
31909566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
31919566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
31929b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
31939566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
31946e2a1849SPeter Brune 
31956e2a1849SPeter Brune     /* copy the function pointers over */
31969566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
31976e2a1849SPeter Brune 
31986e2a1849SPeter Brune     /* default to 1 iteration */
31999566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3200efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
32019566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3202a9936a0cSPeter Brune     } else {
32039566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3204a9936a0cSPeter Brune     }
32059566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
32066e2a1849SPeter Brune 
32076e2a1849SPeter Brune     /* copy the line search context over */
3208d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
32099566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
32109566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
32119566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
32129566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
32139566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
32149566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
32159566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
32166e2a1849SPeter Brune     }
3217d8d34be6SBarry Smith   }
32181baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
321948a46eb9SPierre Jolivet   if (snes->ops->usercompute && !snes->user) PetscCall((*snes->ops->usercompute)(snes, (void **)&snes->user));
32206e2a1849SPeter Brune 
322137ec4e1aSPeter Brune   snes->jac_iter = 0;
322237ec4e1aSPeter Brune   snes->pre_iter = 0;
322337ec4e1aSPeter Brune 
3224dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
322558c9b817SLisandro Dalcin 
32269566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
322758b371f3SBarry Smith 
3228b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
32296c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3230d8d34be6SBarry Smith       if (snes->linesearch) {
32319566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
32329566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
32336c67d002SPeter Brune       }
32346c67d002SPeter Brune     }
3235d8d34be6SBarry Smith   }
3236fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
32377aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
32383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32399b94acceSBarry Smith }
32409b94acceSBarry Smith 
324137596af1SLisandro Dalcin /*@
3242f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
324337596af1SLisandro Dalcin 
3244c3339decSBarry Smith   Collective
324537596af1SLisandro Dalcin 
324637596af1SLisandro Dalcin   Input Parameter:
3247f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
324837596af1SLisandro Dalcin 
3249d25893d9SBarry Smith   Level: intermediate
3250d25893d9SBarry Smith 
325195452b02SPatrick Sanan   Notes:
3252f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
325337596af1SLisandro Dalcin 
3254f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3255f6dfbefdSBarry Smith 
32561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
325737596af1SLisandro Dalcin @*/
3258d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3259d71ae5a4SJacob Faibussowitsch {
326037596af1SLisandro Dalcin   PetscFunctionBegin;
326137596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3262d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
32639566063dSJacob Faibussowitsch     PetscCall((*snes->ops->userdestroy)((void **)&snes->user));
32640298fd71SBarry Smith     snes->user = NULL;
3265d25893d9SBarry Smith   }
32661baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
32678a23116dSBarry Smith 
3268dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
32691baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
32709e764e56SPeter Brune 
32711baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
32729e764e56SPeter Brune 
32739566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
32749566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
32759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
32769566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
32779566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
32789566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
32799566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
32809566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
32819566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3282f5af7f23SKarl Rupp 
328340fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
328440fdac6aSLawrence Mitchell 
328537596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
328637596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
32873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
328837596af1SLisandro Dalcin }
328937596af1SLisandro Dalcin 
329052baeb72SSatish Balay /*@
3291*420bcc1bSBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()`
3292c4421ceaSFande Kong 
3293c3339decSBarry Smith   Collective
3294c4421ceaSFande Kong 
3295c4421ceaSFande Kong   Input Parameter:
3296f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3297c4421ceaSFande Kong 
3298c4421ceaSFande Kong   Level: intermediate
3299c4421ceaSFande Kong 
3300*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3301c4421ceaSFande Kong @*/
3302d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3303d71ae5a4SJacob Faibussowitsch {
3304c4421ceaSFande Kong   PetscInt i;
3305c4421ceaSFande Kong 
3306c4421ceaSFande Kong   PetscFunctionBegin;
3307c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3308c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
330948a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3310c4421ceaSFande Kong   }
3311c4421ceaSFande Kong   snes->numberreasonviews = 0;
33123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3313c4421ceaSFande Kong }
3314c4421ceaSFande Kong 
33151fb7b255SJunchao Zhang /*@C
33169b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3317f6dfbefdSBarry Smith   with `SNESCreate()`.
33189b94acceSBarry Smith 
3319c3339decSBarry Smith   Collective
3320c7afd0dbSLois Curfman McInnes 
33219b94acceSBarry Smith   Input Parameter:
3322f6dfbefdSBarry Smith . snes - the `SNES` context
33239b94acceSBarry Smith 
332436851e7fSLois Curfman McInnes   Level: beginner
332536851e7fSLois Curfman McInnes 
33261cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
33279b94acceSBarry Smith @*/
3328d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3329d71ae5a4SJacob Faibussowitsch {
33303a40ed3dSBarry Smith   PetscFunctionBegin;
33313ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
33326bf464f9SBarry Smith   PetscValidHeaderSpecific((*snes), SNES_CLASSID, 1);
33339371c9d4SSatish Balay   if (--((PetscObject)(*snes))->refct > 0) {
33349371c9d4SSatish Balay     *snes = NULL;
33353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
33369371c9d4SSatish Balay   }
3337d4bb536fSBarry Smith 
33389566063dSJacob Faibussowitsch   PetscCall(SNESReset((*snes)));
33399566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
33406b8b9a38SLisandro Dalcin 
3341e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
33429566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3343dbbe0bcdSBarry Smith   PetscTryTypeMethod((*snes), destroy);
33446d4c513bSLisandro Dalcin 
33459566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
33469566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
33479566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
33489566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
33496b8b9a38SLisandro Dalcin 
33509566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
335148a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
335248a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
33539566063dSJacob Faibussowitsch   PetscCall(SNESMonitorCancel((*snes)));
33549566063dSJacob Faibussowitsch   PetscCall(SNESConvergedReasonViewCancel((*snes)));
33559566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
33563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33579b94acceSBarry Smith }
33589b94acceSBarry Smith 
33599b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
33609b94acceSBarry Smith 
3361a8054027SBarry Smith /*@
3362a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3363a8054027SBarry Smith 
3364c3339decSBarry Smith   Logically Collective
3365a8054027SBarry Smith 
3366a8054027SBarry Smith   Input Parameters:
3367f6dfbefdSBarry Smith + snes - the `SNES` context
3368d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
33693b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3370a8054027SBarry Smith 
3371a8054027SBarry Smith   Options Database Keys:
3372*420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
33733d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3374*420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
33753d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3376a8054027SBarry Smith 
3377dc4c0fb0SBarry Smith   Level: intermediate
3378dc4c0fb0SBarry Smith 
3379*420bcc1bSBarry Smith   Notes:
3380a8054027SBarry Smith   The default is 1
3381*420bcc1bSBarry Smith 
3382f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3383d8e291bfSBarry Smith 
3384f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3385a8054027SBarry Smith 
33861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3387f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3388a8054027SBarry Smith @*/
3389d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3390d71ae5a4SJacob Faibussowitsch {
3391a8054027SBarry Smith   PetscFunctionBegin;
33920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33935f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
33945f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3395c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3396a8054027SBarry Smith   snes->lagpreconditioner = lag;
33973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3398a8054027SBarry Smith }
3399a8054027SBarry Smith 
3400efd51863SBarry Smith /*@
3401f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3402efd51863SBarry Smith 
3403c3339decSBarry Smith   Logically Collective
3404efd51863SBarry Smith 
3405efd51863SBarry Smith   Input Parameters:
3406f6dfbefdSBarry Smith + snes  - the `SNES` context
3407efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3408efd51863SBarry Smith 
3409f6dfbefdSBarry Smith   Options Database Key:
341067b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3411efd51863SBarry Smith 
3412efd51863SBarry Smith   Level: intermediate
3413efd51863SBarry Smith 
3414f6dfbefdSBarry Smith   Note:
3415f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3416c0df2a02SJed Brown 
3417*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
3418*420bcc1bSBarry Smith           `SNESetDM()`
3419efd51863SBarry Smith @*/
3420d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3421d71ae5a4SJacob Faibussowitsch {
3422efd51863SBarry Smith   PetscFunctionBegin;
3423efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3424efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3425efd51863SBarry Smith   snes->gridsequence = steps;
34263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3427efd51863SBarry Smith }
3428efd51863SBarry Smith 
3429fa19ca70SBarry Smith /*@
3430f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3431fa19ca70SBarry Smith 
3432c3339decSBarry Smith   Logically Collective
3433fa19ca70SBarry Smith 
3434fa19ca70SBarry Smith   Input Parameter:
3435f6dfbefdSBarry Smith . snes - the `SNES` context
3436fa19ca70SBarry Smith 
3437fa19ca70SBarry Smith   Output Parameter:
3438fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3439fa19ca70SBarry Smith 
3440fa19ca70SBarry Smith   Level: intermediate
3441fa19ca70SBarry Smith 
34421cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3443fa19ca70SBarry Smith @*/
3444d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3445d71ae5a4SJacob Faibussowitsch {
3446fa19ca70SBarry Smith   PetscFunctionBegin;
3447fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3448fa19ca70SBarry Smith   *steps = snes->gridsequence;
34493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3450fa19ca70SBarry Smith }
3451fa19ca70SBarry Smith 
3452a8054027SBarry Smith /*@
3453f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3454a8054027SBarry Smith 
34553f9fe445SBarry Smith   Not Collective
3456a8054027SBarry Smith 
3457a8054027SBarry Smith   Input Parameter:
3458f6dfbefdSBarry Smith . snes - the `SNES` context
3459a8054027SBarry Smith 
3460a8054027SBarry Smith   Output Parameter:
3461a8054027SBarry 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
34623b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3463a8054027SBarry Smith 
3464dc4c0fb0SBarry Smith   Level: intermediate
3465dc4c0fb0SBarry Smith 
3466a8054027SBarry Smith   Notes:
3467a8054027SBarry Smith   The default is 1
3468f6dfbefdSBarry Smith 
3469a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3470a8054027SBarry Smith 
34711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3472a8054027SBarry Smith @*/
3473d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3474d71ae5a4SJacob Faibussowitsch {
3475a8054027SBarry Smith   PetscFunctionBegin;
34760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3477a8054027SBarry Smith   *lag = snes->lagpreconditioner;
34783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3479a8054027SBarry Smith }
3480a8054027SBarry Smith 
3481e35cf81dSBarry Smith /*@
3482f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3483e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3484e35cf81dSBarry Smith 
3485c3339decSBarry Smith   Logically Collective
3486e35cf81dSBarry Smith 
3487e35cf81dSBarry Smith   Input Parameters:
3488f6dfbefdSBarry Smith + snes - the `SNES` context
3489e35cf81dSBarry 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
3490fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3491e35cf81dSBarry Smith 
3492e35cf81dSBarry Smith   Options Database Keys:
349379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
34943d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
349579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
34963d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3497e35cf81dSBarry Smith 
3498dc4c0fb0SBarry Smith   Level: intermediate
3499dc4c0fb0SBarry Smith 
3500e35cf81dSBarry Smith   Notes:
3501e35cf81dSBarry Smith   The default is 1
3502f6dfbefdSBarry Smith 
3503e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3504f6dfbefdSBarry Smith 
3505fe3ffe1eSBarry 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
3506fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3507e35cf81dSBarry Smith 
35081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3509e35cf81dSBarry Smith @*/
3510d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3511d71ae5a4SJacob Faibussowitsch {
3512e35cf81dSBarry Smith   PetscFunctionBegin;
35130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35145f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35155f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3516c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3517e35cf81dSBarry Smith   snes->lagjacobian = lag;
35183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3519e35cf81dSBarry Smith }
3520e35cf81dSBarry Smith 
3521e35cf81dSBarry Smith /*@
3522f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3523e35cf81dSBarry Smith 
35243f9fe445SBarry Smith   Not Collective
3525e35cf81dSBarry Smith 
3526e35cf81dSBarry Smith   Input Parameter:
3527f6dfbefdSBarry Smith . snes - the `SNES` context
3528e35cf81dSBarry Smith 
3529e35cf81dSBarry Smith   Output Parameter:
3530e35cf81dSBarry 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
3531e35cf81dSBarry Smith          the Jacobian is built etc.
3532e35cf81dSBarry Smith 
3533dc4c0fb0SBarry Smith   Level: intermediate
3534dc4c0fb0SBarry Smith 
3535e35cf81dSBarry Smith   Notes:
3536e35cf81dSBarry Smith   The default is 1
3537f6dfbefdSBarry Smith 
3538f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3539e35cf81dSBarry Smith 
35401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3541e35cf81dSBarry Smith 
3542e35cf81dSBarry Smith @*/
3543d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3544d71ae5a4SJacob Faibussowitsch {
3545e35cf81dSBarry Smith   PetscFunctionBegin;
35460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3547e35cf81dSBarry Smith   *lag = snes->lagjacobian;
35483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3549e35cf81dSBarry Smith }
3550e35cf81dSBarry Smith 
355137ec4e1aSPeter Brune /*@
3552f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
355337ec4e1aSPeter Brune 
3554c3339decSBarry Smith   Logically collective
355537ec4e1aSPeter Brune 
3556d8d19677SJose E. Roman   Input Parameters:
3557f6dfbefdSBarry Smith + snes - the `SNES` context
35589d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
355937ec4e1aSPeter Brune 
356037ec4e1aSPeter Brune   Options Database Keys:
356179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35623d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
356379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35643d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
35653d5a8a6aSBarry Smith 
3566dc4c0fb0SBarry Smith   Level: advanced
3567dc4c0fb0SBarry Smith 
356895452b02SPatrick Sanan   Notes:
3569*420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3570f6dfbefdSBarry Smith 
357195452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
357237ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
357337ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
357437ec4e1aSPeter Brune 
357542747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
357637ec4e1aSPeter Brune @*/
3577d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3578d71ae5a4SJacob Faibussowitsch {
357937ec4e1aSPeter Brune   PetscFunctionBegin;
358037ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
358137ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
358237ec4e1aSPeter Brune   snes->lagjac_persist = flg;
35833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
358437ec4e1aSPeter Brune }
358537ec4e1aSPeter Brune 
358637ec4e1aSPeter Brune /*@
3587d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
358837ec4e1aSPeter Brune 
3589c3339decSBarry Smith   Logically Collective
359037ec4e1aSPeter Brune 
3591d8d19677SJose E. Roman   Input Parameters:
3592f6dfbefdSBarry Smith + snes - the `SNES` context
35939d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
359437ec4e1aSPeter Brune 
359537ec4e1aSPeter Brune   Options Database Keys:
359679a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35973d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
359879a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35993d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
360037ec4e1aSPeter Brune 
3601dc4c0fb0SBarry Smith   Level: developer
3602dc4c0fb0SBarry Smith 
360395452b02SPatrick Sanan   Notes:
3604*420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3605f6dfbefdSBarry Smith 
360695452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
360737ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
360837ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
360937ec4e1aSPeter Brune 
36101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
361137ec4e1aSPeter Brune @*/
3612d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3613d71ae5a4SJacob Faibussowitsch {
361437ec4e1aSPeter Brune   PetscFunctionBegin;
361537ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
361637ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
361737ec4e1aSPeter Brune   snes->lagpre_persist = flg;
36183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
361937ec4e1aSPeter Brune }
362037ec4e1aSPeter Brune 
36219b94acceSBarry Smith /*@
3622f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3623be5caee7SBarry Smith 
3624c3339decSBarry Smith   Logically Collective
3625be5caee7SBarry Smith 
3626be5caee7SBarry Smith   Input Parameters:
3627f6dfbefdSBarry Smith + snes  - the `SNES` context
3628f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3629be5caee7SBarry Smith 
3630f6dfbefdSBarry Smith   Options Database Key:
3631be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3632be5caee7SBarry Smith 
3633dc4c0fb0SBarry Smith   Level: intermediate
3634dc4c0fb0SBarry Smith 
3635f6dfbefdSBarry Smith   Note:
3636f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3637be5caee7SBarry Smith 
36381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3639be5caee7SBarry Smith @*/
3640d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3641d71ae5a4SJacob Faibussowitsch {
3642be5caee7SBarry Smith   PetscFunctionBegin;
3643be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3644be5caee7SBarry Smith   snes->forceiteration = force;
36453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3646be5caee7SBarry Smith }
3647be5caee7SBarry Smith 
364885216dc7SFande Kong /*@
3649f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
365085216dc7SFande Kong 
3651c3339decSBarry Smith   Logically Collective
365285216dc7SFande Kong 
36532fe279fdSBarry Smith   Input Parameter:
3654f6dfbefdSBarry Smith . snes - the `SNES` context
365585216dc7SFande Kong 
365685216dc7SFande Kong   Output Parameter:
3657dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
365885216dc7SFande Kong 
365906dd6b0eSSatish Balay   Level: intermediate
366006dd6b0eSSatish Balay 
36611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
366285216dc7SFande Kong @*/
3663d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3664d71ae5a4SJacob Faibussowitsch {
366585216dc7SFande Kong   PetscFunctionBegin;
366685216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
366785216dc7SFande Kong   *force = snes->forceiteration;
36683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
366985216dc7SFande Kong }
3670be5caee7SBarry Smith 
3671be5caee7SBarry Smith /*@
3672f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
36739b94acceSBarry Smith 
3674c3339decSBarry Smith   Logically Collective
3675c7afd0dbSLois Curfman McInnes 
36769b94acceSBarry Smith   Input Parameters:
3677f6dfbefdSBarry Smith + snes   - the `SNES` context
367870441072SBarry Smith . abstol - absolute convergence tolerance
367933174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
36805358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3681f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
3682f6dfbefdSBarry Smith - maxf   - maximum number of function evaluations (-1 indicates no limit), default 1000
3683fee21e36SBarry Smith 
368433174efeSLois Curfman McInnes   Options Database Keys:
368570441072SBarry Smith + -snes_atol <abstol>    - Sets abstol
3686c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol>      - Sets rtol
3687c7afd0dbSLois Curfman McInnes . -snes_stol <stol>      - Sets stol
3688c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit>   - Sets maxit
3689c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf
36909b94acceSBarry Smith 
369136851e7fSLois Curfman McInnes   Level: intermediate
369236851e7fSLois Curfman McInnes 
36931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
36949b94acceSBarry Smith @*/
3695d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3696d71ae5a4SJacob Faibussowitsch {
36973a40ed3dSBarry Smith   PetscFunctionBegin;
36980700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3699c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3700c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3701c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3702c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3703c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3704c5eb9154SBarry Smith 
370513bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
37065f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3707ab54825eSJed Brown     snes->abstol = abstol;
3708ab54825eSJed Brown   }
370913bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
37105f80ce2aSJacob 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);
3711ab54825eSJed Brown     snes->rtol = rtol;
3712ab54825eSJed Brown   }
371313bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
37145f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3715c60f73f4SPeter Brune     snes->stol = stol;
3716ab54825eSJed Brown   }
3717ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
371863a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3719ab54825eSJed Brown     snes->max_its = maxit;
3720ab54825eSJed Brown   }
3721ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
372263a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3723ab54825eSJed Brown     snes->max_funcs = maxf;
3724ab54825eSJed Brown   }
372588976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
37263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37279b94acceSBarry Smith }
37289b94acceSBarry Smith 
3729e4d06f11SPatrick Farrell /*@
3730f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3731e4d06f11SPatrick Farrell 
3732c3339decSBarry Smith   Logically Collective
3733e4d06f11SPatrick Farrell 
3734e4d06f11SPatrick Farrell   Input Parameters:
3735f6dfbefdSBarry Smith + snes   - the `SNES` context
3736f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3737e4d06f11SPatrick Farrell 
3738f6dfbefdSBarry Smith   Options Database Key:
3739dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3740e4d06f11SPatrick Farrell 
3741e4d06f11SPatrick Farrell   Level: intermediate
3742e4d06f11SPatrick Farrell 
37431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3744e4d06f11SPatrick Farrell @*/
3745d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3746d71ae5a4SJacob Faibussowitsch {
3747e4d06f11SPatrick Farrell   PetscFunctionBegin;
3748e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3749e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3750e4d06f11SPatrick Farrell 
375113bcc0bdSJacob Faibussowitsch   if (divtol != (PetscReal)PETSC_DEFAULT) {
3752e4d06f11SPatrick Farrell     snes->divtol = divtol;
37539371c9d4SSatish Balay   } else {
3754e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3755e4d06f11SPatrick Farrell   }
37563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3757e4d06f11SPatrick Farrell }
3758e4d06f11SPatrick Farrell 
37599b94acceSBarry Smith /*@
376033174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
376133174efeSLois Curfman McInnes 
3762c7afd0dbSLois Curfman McInnes   Not Collective
3763c7afd0dbSLois Curfman McInnes 
376433174efeSLois Curfman McInnes   Input Parameters:
3765f6dfbefdSBarry Smith + snes  - the `SNES` context
376685385478SLisandro Dalcin . atol  - absolute convergence tolerance
376733174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
376833174efeSLois Curfman McInnes . stol  - convergence tolerance in terms of the norm
376933174efeSLois Curfman McInnes            of the change in the solution between steps
377033174efeSLois Curfman McInnes . maxit - maximum number of iterations
3771c7afd0dbSLois Curfman McInnes - maxf  - maximum number of function evaluations
3772fee21e36SBarry Smith 
377336851e7fSLois Curfman McInnes   Level: intermediate
377436851e7fSLois Curfman McInnes 
3775dc4c0fb0SBarry Smith   Note:
3776dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3777dc4c0fb0SBarry Smith 
37781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
377933174efeSLois Curfman McInnes @*/
3780d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3781d71ae5a4SJacob Faibussowitsch {
37823a40ed3dSBarry Smith   PetscFunctionBegin;
37830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
378485385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
378533174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3786c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
378733174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
378833174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
37893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
379033174efeSLois Curfman McInnes }
379133174efeSLois Curfman McInnes 
3792e4d06f11SPatrick Farrell /*@
3793e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3794e4d06f11SPatrick Farrell 
3795e4d06f11SPatrick Farrell   Not Collective
3796e4d06f11SPatrick Farrell 
3797e4d06f11SPatrick Farrell   Input Parameters:
3798f6dfbefdSBarry Smith + snes   - the `SNES` context
3799e4d06f11SPatrick Farrell - divtol - divergence tolerance
3800e4d06f11SPatrick Farrell 
3801e4d06f11SPatrick Farrell   Level: intermediate
3802e4d06f11SPatrick Farrell 
38031cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3804e4d06f11SPatrick Farrell @*/
3805d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3806d71ae5a4SJacob Faibussowitsch {
3807e4d06f11SPatrick Farrell   PetscFunctionBegin;
3808e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3809e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
38103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3811e4d06f11SPatrick Farrell }
3812e4d06f11SPatrick Farrell 
381333174efeSLois Curfman McInnes /*@
38149b94acceSBarry Smith   SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
38159b94acceSBarry Smith 
3816c3339decSBarry Smith   Logically Collective
3817fee21e36SBarry Smith 
3818c7afd0dbSLois Curfman McInnes   Input Parameters:
3819f6dfbefdSBarry Smith + snes - the `SNES` context
3820c7afd0dbSLois Curfman McInnes - tol  - tolerance
3821c7afd0dbSLois Curfman McInnes 
38229b94acceSBarry Smith   Options Database Key:
38234a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol
38249b94acceSBarry Smith 
382536851e7fSLois Curfman McInnes   Level: intermediate
382636851e7fSLois Curfman McInnes 
38271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
38289b94acceSBarry Smith @*/
3829d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3830d71ae5a4SJacob Faibussowitsch {
38313a40ed3dSBarry Smith   PetscFunctionBegin;
38320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3833c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
38349b94acceSBarry Smith   snes->deltatol = tol;
38353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38369b94acceSBarry Smith }
38379b94acceSBarry Smith 
38386ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
38396ba87a44SLisandro Dalcin 
3840d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3841d71ae5a4SJacob Faibussowitsch {
3842b271bb04SBarry Smith   PetscDrawLG      lg;
3843b271bb04SBarry Smith   PetscReal        x, y, per;
3844b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3845b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3846b271bb04SBarry Smith   PetscDraw        draw;
3847b271bb04SBarry Smith 
3848459f5d12SBarry Smith   PetscFunctionBegin;
38494d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
38509566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
38519566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38529566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38539566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3854b271bb04SBarry Smith   x = (PetscReal)n;
385577b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
385694c9c6d3SKarl Rupp   else y = -15.0;
38579566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38586934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38599566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38609566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3861b271bb04SBarry Smith   }
3862b271bb04SBarry Smith 
38639566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
38649566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38659566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
3866aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
38679566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3868b271bb04SBarry Smith   x = (PetscReal)n;
3869b271bb04SBarry Smith   y = 100.0 * per;
38709566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38716934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38729566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38739566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3874b271bb04SBarry Smith   }
3875b271bb04SBarry Smith 
38769566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
38779371c9d4SSatish Balay   if (!n) {
38789371c9d4SSatish Balay     prev = rnorm;
38799371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
38809371c9d4SSatish Balay   }
38819566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38829566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3883b271bb04SBarry Smith   x = (PetscReal)n;
3884b271bb04SBarry Smith   y = (prev - rnorm) / prev;
38859566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
38866934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
38879566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
38889566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3889b271bb04SBarry Smith   }
3890b271bb04SBarry Smith 
38919566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
38929566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
38939566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
38949566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3895b271bb04SBarry Smith   x = (PetscReal)n;
3896b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3897b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
38989566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3899b271bb04SBarry Smith   }
39006934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39019566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39029566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3903b271bb04SBarry Smith   }
3904b271bb04SBarry Smith   prev = rnorm;
39053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3906b271bb04SBarry Smith }
3907b271bb04SBarry Smith 
3908228d79bcSJed Brown /*@
39092d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
39102d157150SStefano Zampini 
39112d157150SStefano Zampini   Collective
39122d157150SStefano Zampini 
39132d157150SStefano Zampini   Input Parameters:
39142d157150SStefano Zampini + snes  - the `SNES` context
39152d157150SStefano Zampini . it    - current iteration
39162d157150SStefano Zampini . xnorm - 2-norm of current iterate
39172d157150SStefano Zampini . snorm - 2-norm of current step
39182d157150SStefano Zampini - fnorm - 2-norm of function
39192d157150SStefano Zampini 
39202d157150SStefano Zampini   Level: developer
39212d157150SStefano Zampini 
39222d157150SStefano Zampini   Note:
3923*420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
39242d157150SStefano Zampini   It does not typically need to be called by the user.
39252d157150SStefano Zampini 
3926be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
39272d157150SStefano Zampini @*/
39282d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
39292d157150SStefano Zampini {
39302d157150SStefano Zampini   PetscFunctionBegin;
39312d157150SStefano Zampini   if (!snes->reason) {
39322d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
39332d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
39342d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
39352d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
39362d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
39372d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
39382d157150SStefano Zampini     }
39392d157150SStefano Zampini   }
39402d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
39412d157150SStefano Zampini }
39422d157150SStefano Zampini 
39432d157150SStefano Zampini /*@
3944228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
3945228d79bcSJed Brown 
3946c3339decSBarry Smith   Collective
3947228d79bcSJed Brown 
3948228d79bcSJed Brown   Input Parameters:
3949f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
3950228d79bcSJed Brown . iter  - iteration number
3951228d79bcSJed Brown - rnorm - relative norm of the residual
3952228d79bcSJed Brown 
3953dc4c0fb0SBarry Smith   Level: developer
3954dc4c0fb0SBarry Smith 
3955f6dfbefdSBarry Smith   Note:
3956*420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
3957228d79bcSJed Brown   It does not typically need to be called by the user.
3958228d79bcSJed Brown 
39591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
3960228d79bcSJed Brown @*/
3961d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
3962d71ae5a4SJacob Faibussowitsch {
39637a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
39647a03ce2fSLisandro Dalcin 
39657a03ce2fSLisandro Dalcin   PetscFunctionBegin;
39665f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
39679566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
396848a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
39699566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
39703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39717a03ce2fSLisandro Dalcin }
39727a03ce2fSLisandro Dalcin 
39739b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
39749b94acceSBarry Smith 
3975bf388a1fSBarry Smith /*MC
3976f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
3977bf388a1fSBarry Smith 
3978bf388a1fSBarry Smith      Synopsis:
3979aaa7dc30SBarry Smith      #include <petscsnes.h>
398037fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
3981bf388a1fSBarry Smith 
3982c3339decSBarry Smith      Collective
39831843f636SBarry Smith 
39841843f636SBarry Smith     Input Parameters:
3985f6dfbefdSBarry Smith +    snes - the `SNES` context
3986bf388a1fSBarry Smith .    its - iteration number
3987bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
3988bf388a1fSBarry Smith -    mctx - [optional] monitoring context
3989bf388a1fSBarry Smith 
3990878cb397SSatish Balay    Level: advanced
3991878cb397SSatish Balay 
39921cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
3993bf388a1fSBarry Smith M*/
3994bf388a1fSBarry Smith 
39959b94acceSBarry Smith /*@C
3996a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
39979b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
39989b94acceSBarry Smith   progress.
39999b94acceSBarry Smith 
4000c3339decSBarry Smith   Logically Collective
4001fee21e36SBarry Smith 
4002c7afd0dbSLois Curfman McInnes   Input Parameters:
4003f6dfbefdSBarry Smith + snes           - the `SNES` context
400420f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4005*420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4006dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
40079b94acceSBarry Smith 
40089665c990SLois Curfman McInnes   Options Database Keys:
4009f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4010798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4011dc4c0fb0SBarry 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
4012c7afd0dbSLois Curfman McInnes                             the options database.
40139665c990SLois Curfman McInnes 
4014dc4c0fb0SBarry Smith   Level: intermediate
4015dc4c0fb0SBarry Smith 
4016f6dfbefdSBarry Smith   Note:
40176bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4018f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
40196bc08f3fSLois Curfman McInnes   order in which they were set.
4020639f9d9dSBarry Smith 
4021*420bcc1bSBarry Smith   Fortran Note:
4022f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4023025f1a04SBarry Smith 
40241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
40259b94acceSBarry Smith @*/
4026d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4027d71ae5a4SJacob Faibussowitsch {
4028b90d0a6eSBarry Smith   PetscInt  i;
402978064530SBarry Smith   PetscBool identical;
4030b90d0a6eSBarry Smith 
40313a40ed3dSBarry Smith   PetscFunctionBegin;
40320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4033b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
40349566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
40353ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4036649052a6SBarry Smith   }
40375f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
40386e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4039b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4040639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
40413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40429b94acceSBarry Smith }
40439b94acceSBarry Smith 
4044a278d85bSSatish Balay /*@
4045f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
40465cd90555SBarry Smith 
4047c3339decSBarry Smith   Logically Collective
4048c7afd0dbSLois Curfman McInnes 
40492fe279fdSBarry Smith   Input Parameter:
4050f6dfbefdSBarry Smith . snes - the `SNES` context
40515cd90555SBarry Smith 
40521a480d89SAdministrator   Options Database Key:
4053a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4054dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4055c7afd0dbSLois Curfman McInnes     set via the options database
40565cd90555SBarry Smith 
4057dc4c0fb0SBarry Smith   Level: intermediate
4058dc4c0fb0SBarry Smith 
4059f6dfbefdSBarry Smith   Note:
4060f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
40615cd90555SBarry Smith 
40621cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
40635cd90555SBarry Smith @*/
4064d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4065d71ae5a4SJacob Faibussowitsch {
4066d952e501SBarry Smith   PetscInt i;
4067d952e501SBarry Smith 
40685cd90555SBarry Smith   PetscFunctionBegin;
40690700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4070d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
407148a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4072d952e501SBarry Smith   }
40735cd90555SBarry Smith   snes->numbermonitors = 0;
40743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40755cd90555SBarry Smith }
40765cd90555SBarry Smith 
4077bf388a1fSBarry Smith /*MC
4078bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4079bf388a1fSBarry Smith 
4080bf388a1fSBarry Smith      Synopsis:
4081aaa7dc30SBarry Smith      #include <petscsnes.h>
408237fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4083bf388a1fSBarry Smith 
4084c3339decSBarry Smith      Collective
40851843f636SBarry Smith 
40861843f636SBarry Smith     Input Parameters:
4087f6dfbefdSBarry Smith +    snes - the `SNES` context
4088bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4089bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4090bf388a1fSBarry Smith .    gnorm - 2-norm of current step
40911843f636SBarry Smith .    f - 2-norm of function
40921843f636SBarry Smith -    cctx - [optional] convergence context
40931843f636SBarry Smith 
40941843f636SBarry Smith     Output Parameter:
40951843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4096bf388a1fSBarry Smith 
4097878cb397SSatish Balay    Level: intermediate
4098bf388a1fSBarry Smith 
40991cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4100bf388a1fSBarry Smith M*/
4101bf388a1fSBarry Smith 
41029b94acceSBarry Smith /*@C
41039b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
41049b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
41059b94acceSBarry Smith 
4106c3339decSBarry Smith   Logically Collective
4107fee21e36SBarry Smith 
4108c7afd0dbSLois Curfman McInnes   Input Parameters:
4109f6dfbefdSBarry Smith + snes                        - the `SNES` context
4110e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4111dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4112dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
41139b94acceSBarry Smith 
411436851e7fSLois Curfman McInnes   Level: advanced
411536851e7fSLois Curfman McInnes 
41161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
41179b94acceSBarry Smith @*/
4118d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4119d71ae5a4SJacob Faibussowitsch {
41203a40ed3dSBarry Smith   PetscFunctionBegin;
41210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4122e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
41231baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4124bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
41257f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
412685385478SLisandro Dalcin   snes->cnvP                  = cctx;
41273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41289b94acceSBarry Smith }
41299b94acceSBarry Smith 
413052baeb72SSatish Balay /*@
4131f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4132184914b5SBarry Smith 
4133184914b5SBarry Smith   Not Collective
4134184914b5SBarry Smith 
4135184914b5SBarry Smith   Input Parameter:
4136f6dfbefdSBarry Smith . snes - the `SNES` context
4137184914b5SBarry Smith 
4138184914b5SBarry Smith   Output Parameter:
4139f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4140184914b5SBarry Smith 
4141f6dfbefdSBarry Smith   Options Database Key:
41426a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
41436a4d7782SBarry Smith 
4144184914b5SBarry Smith   Level: intermediate
4145184914b5SBarry Smith 
4146f6dfbefdSBarry Smith   Note:
4147f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4148184914b5SBarry Smith 
41491cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4150184914b5SBarry Smith @*/
4151d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4152d71ae5a4SJacob Faibussowitsch {
4153184914b5SBarry Smith   PetscFunctionBegin;
41540700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41554f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4156184914b5SBarry Smith   *reason = snes->reason;
41573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4158184914b5SBarry Smith }
4159184914b5SBarry Smith 
4160c4421ceaSFande Kong /*@C
4161f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4162c4421ceaSFande Kong 
4163c4421ceaSFande Kong   Not Collective
4164c4421ceaSFande Kong 
4165c4421ceaSFande Kong   Input Parameter:
4166f6dfbefdSBarry Smith . snes - the `SNES` context
4167c4421ceaSFande Kong 
4168c4421ceaSFande Kong   Output Parameter:
4169dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4170c4421ceaSFande Kong 
417199c90e12SSatish Balay   Level: beginner
4172c4421ceaSFande Kong 
41731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4174c4421ceaSFande Kong @*/
4175d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4176d71ae5a4SJacob Faibussowitsch {
4177c4421ceaSFande Kong   PetscFunctionBegin;
4178c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
41794f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4180c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
41813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4182c4421ceaSFande Kong }
4183c4421ceaSFande Kong 
418433866048SMatthew G. Knepley /*@
4185f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
418633866048SMatthew G. Knepley 
418733866048SMatthew G. Knepley   Not Collective
418833866048SMatthew G. Knepley 
418933866048SMatthew G. Knepley   Input Parameters:
4190f6dfbefdSBarry Smith + snes   - the `SNES` context
4191f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
419233866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
419333866048SMatthew G. Knepley 
4194f6dfbefdSBarry Smith   Level: developer
4195f6dfbefdSBarry Smith 
4196*420bcc1bSBarry Smith   Developer Note:
4197f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
419833866048SMatthew G. Knepley 
41991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
420033866048SMatthew G. Knepley @*/
4201d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4202d71ae5a4SJacob Faibussowitsch {
420333866048SMatthew G. Knepley   PetscFunctionBegin;
420433866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42055f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
420633866048SMatthew G. Knepley   snes->reason = reason;
42073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
420833866048SMatthew G. Knepley }
420933866048SMatthew G. Knepley 
4210c9005455SLois Curfman McInnes /*@
4211*420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4212c9005455SLois Curfman McInnes 
4213c3339decSBarry Smith   Logically Collective
4214fee21e36SBarry Smith 
4215c7afd0dbSLois Curfman McInnes   Input Parameters:
4216f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
42178c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4218cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4219*420bcc1bSBarry Smith . na    - size of `a` and `its`
4220f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4221758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4222c7afd0dbSLois Curfman McInnes 
4223dc4c0fb0SBarry Smith   Level: intermediate
4224dc4c0fb0SBarry Smith 
4225308dcc3eSBarry Smith   Notes:
4226dc4c0fb0SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4227308dcc3eSBarry Smith   default array of length 10000 is allocated.
4228308dcc3eSBarry Smith 
4229c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4230c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4231c9005455SLois Curfman McInnes   during the section of code that is being timed.
4232c9005455SLois Curfman McInnes 
4233*420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4234*420bcc1bSBarry Smith 
42351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4236c9005455SLois Curfman McInnes @*/
4237d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4238d71ae5a4SJacob Faibussowitsch {
42393a40ed3dSBarry Smith   PetscFunctionBegin;
42400700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42414f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
42424f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
42437a1ec6d4SBarry Smith   if (!a) {
4244308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
42459566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4246071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4247308dcc3eSBarry Smith   }
4248c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4249758f92a0SBarry Smith   snes->conv_hist_its   = its;
4250115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4251a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4252758f92a0SBarry Smith   snes->conv_hist_reset = reset;
42533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4254758f92a0SBarry Smith }
4255758f92a0SBarry Smith 
4256d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4257c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4258c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
425999e0435eSBarry Smith 
4260d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4261d71ae5a4SJacob Faibussowitsch {
4262308dcc3eSBarry Smith   mxArray   *mat;
4263308dcc3eSBarry Smith   PetscInt   i;
4264308dcc3eSBarry Smith   PetscReal *ar;
4265308dcc3eSBarry Smith 
4266308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4267308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4268f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
426911cc89d2SBarry Smith   return mat;
4270308dcc3eSBarry Smith }
4271308dcc3eSBarry Smith #endif
4272308dcc3eSBarry Smith 
42730c4c9dddSBarry Smith /*@C
4274*420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4275758f92a0SBarry Smith 
42763f9fe445SBarry Smith   Not Collective
4277758f92a0SBarry Smith 
4278758f92a0SBarry Smith   Input Parameter:
4279f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4280758f92a0SBarry Smith 
4281758f92a0SBarry Smith   Output Parameters:
4282f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4283758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4284758f92a0SBarry Smith          negative if not converged) for each solve.
428520f4b53cSBarry Smith - na  - size of `a` and `its`
4286758f92a0SBarry Smith 
4287dc4c0fb0SBarry Smith   Level: intermediate
4288dc4c0fb0SBarry Smith 
428920f4b53cSBarry Smith   Note:
429020f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
429120f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
429220f4b53cSBarry Smith   during the section of code that is being timed.
429320f4b53cSBarry Smith 
4294*420bcc1bSBarry Smith   Fortran Note:
4295758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4296dc4c0fb0SBarry Smith .vb
4297dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4298dc4c0fb0SBarry Smith .ve
4299758f92a0SBarry Smith 
43001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4301758f92a0SBarry Smith @*/
4302d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4303d71ae5a4SJacob Faibussowitsch {
4304758f92a0SBarry Smith   PetscFunctionBegin;
43050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4306758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4307758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4308115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
43093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4310c9005455SLois Curfman McInnes }
4311c9005455SLois Curfman McInnes 
4312ac226902SBarry Smith /*@C
431376b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4314eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
43157e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
431676b2cf59SMatthew Knepley 
4317c3339decSBarry Smith   Logically Collective
431876b2cf59SMatthew Knepley 
431976b2cf59SMatthew Knepley   Input Parameters:
4320a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4321a2b725a8SWilliam Gropp - func - The function
432276b2cf59SMatthew Knepley 
432320f4b53cSBarry Smith   Calling sequence of `func`:
432420f4b53cSBarry Smith + snes - the nonlinear solver context
432520f4b53cSBarry Smith - step - The current step of the iteration
432676b2cf59SMatthew Knepley 
4327fe97e370SBarry Smith   Level: advanced
4328fe97e370SBarry Smith 
4329*420bcc1bSBarry Smith   Notes:
4330f6dfbefdSBarry 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
4331f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
4332fe97e370SBarry Smith   This is not used by most users.
433376b2cf59SMatthew Knepley 
4334aaa8cc7dSPierre 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.
43356b7fb656SBarry Smith 
4336e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4337db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
433876b2cf59SMatthew Knepley @*/
43390b4db180SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES snes, PetscInt step))
4340d71ae5a4SJacob Faibussowitsch {
434176b2cf59SMatthew Knepley   PetscFunctionBegin;
43420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4343e7788613SBarry Smith   snes->ops->update = func;
43443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
434576b2cf59SMatthew Knepley }
434676b2cf59SMatthew Knepley 
434791f3e32bSBarry Smith /*@C
4348f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
43492a359c20SBarry Smith 
4350c3339decSBarry Smith   Collective
43512a359c20SBarry Smith 
4352e4094ef1SJacob Faibussowitsch   Input Parameters:
4353f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
43542a359c20SBarry Smith - viewer - the viewer to display the reason
43552a359c20SBarry Smith 
43562a359c20SBarry Smith   Options Database Keys:
4357ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4358ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4359eafd5ff0SAlex Lindsay 
4360*420bcc1bSBarry Smith   Level: beginner
4361*420bcc1bSBarry Smith 
4362f6dfbefdSBarry Smith   Note:
4363f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4364f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
43652a359c20SBarry Smith 
43661cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4367f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4368f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4369db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
43702a359c20SBarry Smith @*/
4371d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4372d71ae5a4SJacob Faibussowitsch {
437375cca76cSMatthew G. Knepley   PetscViewerFormat format;
43742a359c20SBarry Smith   PetscBool         isAscii;
43752a359c20SBarry Smith 
43762a359c20SBarry Smith   PetscFunctionBegin;
437719a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
43789566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
43792a359c20SBarry Smith   if (isAscii) {
43809566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
43819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
438275cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
438375cca76cSMatthew G. Knepley       DM       dm;
438475cca76cSMatthew G. Knepley       Vec      u;
438575cca76cSMatthew G. Knepley       PetscDS  prob;
438675cca76cSMatthew G. Knepley       PetscInt Nf, f;
438795cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
438895cbbfd3SMatthew G. Knepley       void    **exactCtx;
438975cca76cSMatthew G. Knepley       PetscReal error;
439075cca76cSMatthew G. Knepley 
43919566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
43929566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
43939566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
43949566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
43959566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
43969566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
43979566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
43989566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
43999566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
440063a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
440175cca76cSMatthew G. Knepley     }
4402eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
44032a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
440463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
44052a359c20SBarry Smith       } else {
440663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44072a359c20SBarry Smith       }
4408eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
44092a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
441063a3b9bcSJacob 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));
44112a359c20SBarry Smith       } else {
441263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44132a359c20SBarry Smith       }
44142a359c20SBarry Smith     }
44159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
44162a359c20SBarry Smith   }
44173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44182a359c20SBarry Smith }
44192a359c20SBarry Smith 
4420c4421ceaSFande Kong /*@C
4421c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4422aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4423c4421ceaSFande Kong 
4424c3339decSBarry Smith   Logically Collective
4425c4421ceaSFande Kong 
4426c4421ceaSFande Kong   Input Parameters:
4427f6dfbefdSBarry Smith + snes              - the `SNES` context
4428*420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4429*420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4430*420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`)
4431*420bcc1bSBarry Smith 
4432*420bcc1bSBarry Smith   Calling sequence of `f`:
4433*420bcc1bSBarry Smith + snes - the `SNES` context
4434*420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function
4435*420bcc1bSBarry Smith 
4436*420bcc1bSBarry Smith   Calling sequence of `reasonviewerdestroy`:
4437*420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function
4438c4421ceaSFande Kong 
4439c4421ceaSFande Kong   Options Database Keys:
4440f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4441*420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4442*420bcc1bSBarry Smith                             calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4443c4421ceaSFande Kong 
4444dc4c0fb0SBarry Smith   Level: intermediate
4445dc4c0fb0SBarry Smith 
4446f6dfbefdSBarry Smith   Note:
4447c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4448f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4449c4421ceaSFande Kong   order in which they were set.
4450c4421ceaSFande Kong 
44511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4452c4421ceaSFande Kong @*/
4453*420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx))
4454d71ae5a4SJacob Faibussowitsch {
4455c4421ceaSFande Kong   PetscInt  i;
4456c4421ceaSFande Kong   PetscBool identical;
4457c4421ceaSFande Kong 
4458c4421ceaSFande Kong   PetscFunctionBegin;
4459c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4460c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
44619566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
44623ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4463c4421ceaSFande Kong   }
44645f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4465c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4466c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4467c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
44683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4469c4421ceaSFande Kong }
4470c4421ceaSFande Kong 
447191f3e32bSBarry Smith /*@
4472*420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4473c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
44742a359c20SBarry Smith 
4475c3339decSBarry Smith   Collective
44762a359c20SBarry Smith 
44772fe279fdSBarry Smith   Input Parameter:
4478f6dfbefdSBarry Smith . snes - the `SNES` object
44792a359c20SBarry Smith 
4480f6dfbefdSBarry Smith   Level: advanced
44812a359c20SBarry Smith 
44821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4483f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
44842a359c20SBarry Smith @*/
4485d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4486d71ae5a4SJacob Faibussowitsch {
44872a359c20SBarry Smith   PetscViewer       viewer;
44882a359c20SBarry Smith   PetscBool         flg;
44892a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
44902a359c20SBarry Smith   PetscViewerFormat format;
4491c4421ceaSFande Kong   PetscInt          i;
44922a359c20SBarry Smith 
44932a359c20SBarry Smith   PetscFunctionBegin;
44943ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
44952a359c20SBarry Smith   incall = PETSC_TRUE;
4496c4421ceaSFande Kong 
4497c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
449848a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4499c4421ceaSFande Kong 
4500c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
45019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
45022a359c20SBarry Smith   if (flg) {
45039566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
45049566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
45059566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
45069566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
45072a359c20SBarry Smith   }
45082a359c20SBarry Smith   incall = PETSC_FALSE;
45093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45102a359c20SBarry Smith }
45112a359c20SBarry Smith 
4512487a658cSBarry Smith /*@
4513f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
45149b94acceSBarry Smith 
4515c3339decSBarry Smith   Collective
4516c7afd0dbSLois Curfman McInnes 
4517b2002411SLois Curfman McInnes   Input Parameters:
4518f6dfbefdSBarry Smith + snes - the `SNES` context
4519dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
452085385478SLisandro Dalcin - x    - the solution vector.
45219b94acceSBarry Smith 
4522dc4c0fb0SBarry Smith   Level: beginner
4523dc4c0fb0SBarry Smith 
4524f6dfbefdSBarry Smith   Note:
4525*420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4526*420bcc1bSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
45278ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4528f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
45298ddd3da0SLois Curfman McInnes 
45301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4531db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4532*420bcc1bSBarry Smith           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
45339b94acceSBarry Smith @*/
4534d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4535d71ae5a4SJacob Faibussowitsch {
4536ace3abfcSBarry Smith   PetscBool flg;
4537efd51863SBarry Smith   PetscInt  grid;
45380298fd71SBarry Smith   Vec       xcreated = NULL;
4539caa4e7f2SJed Brown   DM        dm;
4540052efed2SBarry Smith 
45413a40ed3dSBarry Smith   PetscFunctionBegin;
45420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4543a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4544a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
45450700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
454685385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
454785385478SLisandro Dalcin 
454834b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
454906fc46c8SMatthew G. Knepley   {
455006fc46c8SMatthew G. Knepley     PetscViewer       viewer;
455106fc46c8SMatthew G. Knepley     PetscViewerFormat format;
45527c88af5aSMatthew G. Knepley     PetscInt          num;
455306fc46c8SMatthew G. Knepley     PetscBool         flg;
455406fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
455506fc46c8SMatthew G. Knepley 
455606fc46c8SMatthew G. Knepley     if (!incall) {
455734b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
45589566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
455906fc46c8SMatthew G. Knepley       if (flg) {
456006fc46c8SMatthew G. Knepley         PetscConvEst conv;
456146079b62SMatthew G. Knepley         DM           dm;
456246079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
456346079b62SMatthew G. Knepley         PetscInt     Nf;
456406fc46c8SMatthew G. Knepley 
456506fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
45669566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
45679566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
45689566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
45699566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
45709566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
45719566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
45729566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
45739566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
45749566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
45759566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
45769566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
45779566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
45789566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
45799566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
458006fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
458106fc46c8SMatthew G. Knepley       }
458234b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4583b2588ea6SMatthew G. Knepley       num = 1;
45849566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
458534b4d3a8SMatthew G. Knepley       if (flg) {
458634b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
458734b4d3a8SMatthew G. Knepley 
458834b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
45899566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
45909566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
45919566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
45929566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
45939566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
45949566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
45959566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
459634b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
459734b4d3a8SMatthew G. Knepley       }
45987c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
45997c88af5aSMatthew G. Knepley       num = 0;
46009566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
46017c88af5aSMatthew G. Knepley       if (num) {
46027c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
46037c88af5aSMatthew G. Knepley 
46047c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
46059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46069566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46079566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46089566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46099566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46109566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
46119566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
46127c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
46137c88af5aSMatthew G. Knepley       }
461406fc46c8SMatthew G. Knepley     }
461506fc46c8SMatthew G. Knepley   }
4616ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4617caa4e7f2SJed Brown   if (!x) {
46189566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
46199566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4620a69afd8bSBarry Smith     x = xcreated;
4621a69afd8bSBarry Smith   }
46229566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4623f05ece33SBarry Smith 
46249566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4625efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
462685385478SLisandro Dalcin     /* set solution vector */
46279566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
46289566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
462985385478SLisandro Dalcin     snes->vec_sol = x;
46309566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4631caa4e7f2SJed Brown 
4632caa4e7f2SJed Brown     /* set affine vector if provided */
46339566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
46349566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
463585385478SLisandro Dalcin     snes->vec_rhs = b;
463685385478SLisandro Dalcin 
46375f80ce2aSJacob 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");
46385f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
46395f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right hand side vector");
4640aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
46419566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
46429566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
46433f149594SLisandro Dalcin 
46447eee914bSBarry Smith     if (!grid) {
464525e27a38SBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4646dd568438SSatish Balay     }
4647d25893d9SBarry Smith 
4648abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
46499371c9d4SSatish Balay     if (snes->counters_reset) {
46509371c9d4SSatish Balay       snes->nfuncs      = 0;
46519371c9d4SSatish Balay       snes->linear_its  = 0;
46529371c9d4SSatish Balay       snes->numFailures = 0;
46539371c9d4SSatish Balay     }
4654d5e45103SBarry Smith 
46552d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
46569566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4657dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
46589566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
46592d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4660422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
46613f149594SLisandro Dalcin 
466237ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
466337ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
466437ec4e1aSPeter Brune 
46659566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
46669566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4667c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
46689566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
46695968eb51SBarry Smith 
46705f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
46719c8e83a9SBarry Smith     if (snes->reason < 0) break;
4672efd51863SBarry Smith     if (grid < snes->gridsequence) {
4673efd51863SBarry Smith       DM  fine;
4674efd51863SBarry Smith       Vec xnew;
4675efd51863SBarry Smith       Mat interp;
4676efd51863SBarry Smith 
46779566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
46785f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
46799566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
46809566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
46819566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
46829566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
46839566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4684efd51863SBarry Smith       x = xnew;
4685efd51863SBarry Smith 
46869566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
46879566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
46889566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
46899566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
46909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4691efd51863SBarry Smith     }
4692efd51863SBarry Smith   }
46939566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
46949566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
46959566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
46969566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
46973f7e2da0SPeter Brune 
46989566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
46999566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
47003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47019b94acceSBarry Smith }
47029b94acceSBarry Smith 
47039b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
47049b94acceSBarry Smith 
470582bf6240SBarry Smith /*@C
47064b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
47079b94acceSBarry Smith 
4708c3339decSBarry Smith   Collective
4709fee21e36SBarry Smith 
4710c7afd0dbSLois Curfman McInnes   Input Parameters:
4711f6dfbefdSBarry Smith + snes - the `SNES` context
4712454a90a3SBarry Smith - type - a known method
4713c7afd0dbSLois Curfman McInnes 
4714c7afd0dbSLois Curfman McInnes   Options Database Key:
4715454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
471604d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4717ae12b187SLois Curfman McInnes 
4718dc4c0fb0SBarry Smith   Level: intermediate
4719dc4c0fb0SBarry Smith 
47209b94acceSBarry Smith   Notes:
4721e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4722f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4723c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
47244a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4725c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
47269b94acceSBarry Smith 
4727f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4728f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4729ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4730ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4731f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4732ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4733ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4734ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4735ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4736b0a32e0cSBarry Smith   appropriate method.
473736851e7fSLois Curfman McInnes 
4738*420bcc1bSBarry Smith   Developer Note:
4739f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4740f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
47418f6c3df8SBarry Smith 
47421cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
47439b94acceSBarry Smith @*/
4744d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4745d71ae5a4SJacob Faibussowitsch {
4746ace3abfcSBarry Smith   PetscBool match;
47475f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
47483a40ed3dSBarry Smith 
47493a40ed3dSBarry Smith   PetscFunctionBegin;
47500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47514f572ea9SToby Isaac   PetscAssertPointer(type, 2);
475282bf6240SBarry Smith 
47539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
47543ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
475592ff6ae8SBarry Smith 
47569566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
47576adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
475875396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4759dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
476075396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
47619e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
47629e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
47639e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
47649e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
47659e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
47667fe760d5SStefano Zampini 
47677fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
47689566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
47697fe760d5SStefano Zampini 
477075396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
477175396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4772f5af7f23SKarl Rupp 
47739566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
47749566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
47753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47769b94acceSBarry Smith }
47779b94acceSBarry Smith 
47789b94acceSBarry Smith /*@C
4779f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
47809b94acceSBarry Smith 
4781c7afd0dbSLois Curfman McInnes   Not Collective
4782c7afd0dbSLois Curfman McInnes 
47839b94acceSBarry Smith   Input Parameter:
47844b0e389bSBarry Smith . snes - nonlinear solver context
47859b94acceSBarry Smith 
47869b94acceSBarry Smith   Output Parameter:
4787f6dfbefdSBarry Smith . type - `SNES` method (a character string)
47889b94acceSBarry Smith 
478936851e7fSLois Curfman McInnes   Level: intermediate
479036851e7fSLois Curfman McInnes 
47911cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
47929b94acceSBarry Smith @*/
4793d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4794d71ae5a4SJacob Faibussowitsch {
47953a40ed3dSBarry Smith   PetscFunctionBegin;
47960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
47974f572ea9SToby Isaac   PetscAssertPointer(type, 2);
47987adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
47993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48009b94acceSBarry Smith }
48019b94acceSBarry Smith 
48023cd8a7caSMatthew G. Knepley /*@
4803f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
48043cd8a7caSMatthew G. Knepley 
4805c3339decSBarry Smith   Logically Collective
48063cd8a7caSMatthew G. Knepley 
48073cd8a7caSMatthew G. Knepley   Input Parameters:
4808f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
48093cd8a7caSMatthew G. Knepley - u    - the solution vector
48103cd8a7caSMatthew G. Knepley 
48113cd8a7caSMatthew G. Knepley   Level: beginner
48123cd8a7caSMatthew G. Knepley 
48131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
48143cd8a7caSMatthew G. Knepley @*/
4815d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4816d71ae5a4SJacob Faibussowitsch {
48173cd8a7caSMatthew G. Knepley   DM dm;
48183cd8a7caSMatthew G. Knepley 
48193cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
48203cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48213cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
48229566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
48239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
48243cd8a7caSMatthew G. Knepley 
48253cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
48263cd8a7caSMatthew G. Knepley 
48279566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
48289566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
48293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48303cd8a7caSMatthew G. Knepley }
48313cd8a7caSMatthew G. Knepley 
483252baeb72SSatish Balay /*@
48339b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
4834f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
48359b94acceSBarry Smith 
4836*420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4837c7afd0dbSLois Curfman McInnes 
48389b94acceSBarry Smith   Input Parameter:
4839f6dfbefdSBarry Smith . snes - the `SNES` context
48409b94acceSBarry Smith 
48419b94acceSBarry Smith   Output Parameter:
48429b94acceSBarry Smith . x - the solution
48439b94acceSBarry Smith 
484470e92668SMatthew Knepley   Level: intermediate
484536851e7fSLois Curfman McInnes 
48461cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
48479b94acceSBarry Smith @*/
4848d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4849d71ae5a4SJacob Faibussowitsch {
48503a40ed3dSBarry Smith   PetscFunctionBegin;
48510700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48524f572ea9SToby Isaac   PetscAssertPointer(x, 2);
485385385478SLisandro Dalcin   *x = snes->vec_sol;
48543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
485570e92668SMatthew Knepley }
485670e92668SMatthew Knepley 
485752baeb72SSatish Balay /*@
48589b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
48599b94acceSBarry Smith   stored.
48609b94acceSBarry Smith 
4861*420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4862c7afd0dbSLois Curfman McInnes 
48639b94acceSBarry Smith   Input Parameter:
4864f6dfbefdSBarry Smith . snes - the `SNES` context
48659b94acceSBarry Smith 
48669b94acceSBarry Smith   Output Parameter:
48679b94acceSBarry Smith . x - the solution update
48689b94acceSBarry Smith 
486936851e7fSLois Curfman McInnes   Level: advanced
487036851e7fSLois Curfman McInnes 
48711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
48729b94acceSBarry Smith @*/
4873d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4874d71ae5a4SJacob Faibussowitsch {
48753a40ed3dSBarry Smith   PetscFunctionBegin;
48760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48774f572ea9SToby Isaac   PetscAssertPointer(x, 2);
487885385478SLisandro Dalcin   *x = snes->vec_sol_update;
48793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48809b94acceSBarry Smith }
48819b94acceSBarry Smith 
48829b94acceSBarry Smith /*@C
4883f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
48849b94acceSBarry Smith 
4885*420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
4886c7afd0dbSLois Curfman McInnes 
48879b94acceSBarry Smith   Input Parameter:
4888f6dfbefdSBarry Smith . snes - the `SNES` context
48899b94acceSBarry Smith 
4890d8d19677SJose E. Roman   Output Parameters:
4891dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
489220f4b53cSBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunction`
4893dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
48949b94acceSBarry Smith 
489536851e7fSLois Curfman McInnes   Level: advanced
489636851e7fSLois Curfman McInnes 
4897f6dfbefdSBarry Smith   Note:
4898dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
489904edfde5SBarry Smith 
4900e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunction`
49019b94acceSBarry Smith @*/
4902d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunction(SNES snes, Vec *r, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4903d71ae5a4SJacob Faibussowitsch {
49046cab3a1bSJed Brown   DM dm;
4905a63bb30eSJed Brown 
49063a40ed3dSBarry Smith   PetscFunctionBegin;
49070700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4908a63bb30eSJed Brown   if (r) {
4909a63bb30eSJed Brown     if (!snes->vec_func) {
4910a63bb30eSJed Brown       if (snes->vec_rhs) {
49119566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
4912a63bb30eSJed Brown       } else if (snes->vec_sol) {
49139566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
4914a63bb30eSJed Brown       } else if (snes->dm) {
49159566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
4916a63bb30eSJed Brown       }
4917a63bb30eSJed Brown     }
4918a63bb30eSJed Brown     *r = snes->vec_func;
4919a63bb30eSJed Brown   }
49209566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49219566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
49223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49239b94acceSBarry Smith }
49249b94acceSBarry Smith 
4925c79ef259SPeter Brune /*@C
492637fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
4927c79ef259SPeter Brune 
4928c79ef259SPeter Brune   Input Parameter:
4929f6dfbefdSBarry Smith . snes - the `SNES` context
4930c79ef259SPeter Brune 
4931d8d19677SJose E. Roman   Output Parameters:
493237fdd005SBarry Smith + f   - the function (or `NULL`) see `SNESSetNGS()` for details
4933dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
4934c79ef259SPeter Brune 
4935c79ef259SPeter Brune   Level: advanced
4936c79ef259SPeter Brune 
49371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`
4938c79ef259SPeter Brune @*/
4939d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNGS(SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void *), void **ctx)
4940d71ae5a4SJacob Faibussowitsch {
49416cab3a1bSJed Brown   DM dm;
49426cab3a1bSJed Brown 
4943646217ecSPeter Brune   PetscFunctionBegin;
4944646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49459566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49469566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
49473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4948646217ecSPeter Brune }
4949646217ecSPeter Brune 
49503c7409f5SSatish Balay /*@C
49513c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
4952f6dfbefdSBarry Smith   `SNES` options in the database.
49533c7409f5SSatish Balay 
4954c3339decSBarry Smith   Logically Collective
4955fee21e36SBarry Smith 
4956d8d19677SJose E. Roman   Input Parameters:
4957f6dfbefdSBarry Smith + snes   - the `SNES` context
4958c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
4959c7afd0dbSLois Curfman McInnes 
4960dc4c0fb0SBarry Smith   Level: advanced
4961dc4c0fb0SBarry Smith 
4962f6dfbefdSBarry Smith   Note:
4963a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
4964c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
4965d850072dSLois Curfman McInnes 
49661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
49673c7409f5SSatish Balay @*/
4968d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
4969d71ae5a4SJacob Faibussowitsch {
49703a40ed3dSBarry Smith   PetscFunctionBegin;
49710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49729566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
49739566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
497435f5d045SPeter Brune   if (snes->linesearch) {
49759566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
49769566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
497735f5d045SPeter Brune   }
49789566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
49793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49803c7409f5SSatish Balay }
49813c7409f5SSatish Balay 
49823c7409f5SSatish Balay /*@C
4983f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
4984f6dfbefdSBarry Smith   `SNES` options in the database.
49853c7409f5SSatish Balay 
4986c3339decSBarry Smith   Logically Collective
4987fee21e36SBarry Smith 
4988c7afd0dbSLois Curfman McInnes   Input Parameters:
4989f6dfbefdSBarry Smith + snes   - the `SNES` context
4990c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
4991c7afd0dbSLois Curfman McInnes 
4992dc4c0fb0SBarry Smith   Level: advanced
4993dc4c0fb0SBarry Smith 
4994f6dfbefdSBarry Smith   Note:
4995a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
4996c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
4997d850072dSLois Curfman McInnes 
49981cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
49993c7409f5SSatish Balay @*/
5000d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5001d71ae5a4SJacob Faibussowitsch {
50023a40ed3dSBarry Smith   PetscFunctionBegin;
50030700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50049566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
50059566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
500635f5d045SPeter Brune   if (snes->linesearch) {
50079566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50089566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
500935f5d045SPeter Brune   }
50109566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
50113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50123c7409f5SSatish Balay }
50133c7409f5SSatish Balay 
50149ab63eb5SSatish Balay /*@C
5015f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5016f6dfbefdSBarry Smith   `SNES` options in the database.
50173c7409f5SSatish Balay 
5018c7afd0dbSLois Curfman McInnes   Not Collective
5019c7afd0dbSLois Curfman McInnes 
50203c7409f5SSatish Balay   Input Parameter:
5021f6dfbefdSBarry Smith . snes - the `SNES` context
50223c7409f5SSatish Balay 
50233c7409f5SSatish Balay   Output Parameter:
50243c7409f5SSatish Balay . prefix - pointer to the prefix string used
50253c7409f5SSatish Balay 
502636851e7fSLois Curfman McInnes   Level: advanced
502736851e7fSLois Curfman McInnes 
5028*420bcc1bSBarry Smith   Fortran Note:
5029dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5030dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5031dc4c0fb0SBarry Smith 
50321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
50333c7409f5SSatish Balay @*/
5034d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5035d71ae5a4SJacob Faibussowitsch {
50363a40ed3dSBarry Smith   PetscFunctionBegin;
50370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50389566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
50393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50403c7409f5SSatish Balay }
50413c7409f5SSatish Balay 
50423cea93caSBarry Smith /*@C
50431c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
50441c84c290SBarry Smith 
504520f4b53cSBarry Smith   Not Collective
50461c84c290SBarry Smith 
50471c84c290SBarry Smith   Input Parameters:
504820f4b53cSBarry Smith + sname    - name of a new user-defined solver
504920f4b53cSBarry Smith - function - routine to create method context
50501c84c290SBarry Smith 
5051dc4c0fb0SBarry Smith   Level: advanced
5052dc4c0fb0SBarry Smith 
5053f6dfbefdSBarry Smith   Note:
5054f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
50551c84c290SBarry Smith 
5056e4094ef1SJacob Faibussowitsch   Example Usage:
50571c84c290SBarry Smith .vb
5058bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
50591c84c290SBarry Smith .ve
50601c84c290SBarry Smith 
50611c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
50621c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
50631c84c290SBarry Smith   or at runtime via the option
50641c84c290SBarry Smith $     -snes_type my_solver
50651c84c290SBarry Smith 
50661cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
50673cea93caSBarry Smith @*/
5068d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5069d71ae5a4SJacob Faibussowitsch {
5070b2002411SLois Curfman McInnes   PetscFunctionBegin;
50719566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
50729566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
50733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5074b2002411SLois Curfman McInnes }
5075da9b6338SBarry Smith 
5076d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5077d71ae5a4SJacob Faibussowitsch {
507877431f27SBarry Smith   PetscInt    N, i, j;
5079da9b6338SBarry Smith   Vec         u, uh, fh;
5080da9b6338SBarry Smith   PetscScalar value;
5081da9b6338SBarry Smith   PetscReal   norm;
5082da9b6338SBarry Smith 
5083da9b6338SBarry Smith   PetscFunctionBegin;
50849566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
50859566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
50869566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5087da9b6338SBarry Smith 
5088da9b6338SBarry Smith   /* currently only works for sequential */
50899566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
50909566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5091da9b6338SBarry Smith   for (i = 0; i < N; i++) {
50929566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
509363a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5094da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
50958b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
50969566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
50979566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
50989566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
509963a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5100da9b6338SBarry Smith       value = -value;
51019566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5102da9b6338SBarry Smith     }
5103da9b6338SBarry Smith   }
51049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
51059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
51063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5107da9b6338SBarry Smith }
510871f87433Sdalcinl 
510971f87433Sdalcinl /*@
5110f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
511171f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
511271f87433Sdalcinl   Newton method.
511371f87433Sdalcinl 
5114c3339decSBarry Smith   Logically Collective
511571f87433Sdalcinl 
511671f87433Sdalcinl   Input Parameters:
5117f6dfbefdSBarry Smith + snes - `SNES` context
5118f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
511971f87433Sdalcinl 
5120f6dfbefdSBarry Smith   Options Database Keys:
512164ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
512264ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
512364ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
512464ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
512564ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
512664ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
512764ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
512864ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
512964ba62caSBarry Smith 
5130dc4c0fb0SBarry Smith   Level: advanced
5131dc4c0fb0SBarry Smith 
5132f6dfbefdSBarry Smith   Note:
5133f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
513471f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
513571f87433Sdalcinl   Eisenstat-Walker method, where the relative convergence tolerance
513671f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
513771f87433Sdalcinl   solver.
513871f87433Sdalcinl 
5139e4094ef1SJacob Faibussowitsch   References:
5140f6dfbefdSBarry Smith .  - * S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an inexact Newton method", SISC 17 (1), pp.16-32, 1996.
514171f87433Sdalcinl 
51421cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
514371f87433Sdalcinl @*/
5144d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5145d71ae5a4SJacob Faibussowitsch {
514671f87433Sdalcinl   PetscFunctionBegin;
51470700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5148acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
514971f87433Sdalcinl   snes->ksp_ewconv = flag;
51503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515171f87433Sdalcinl }
515271f87433Sdalcinl 
515371f87433Sdalcinl /*@
5154f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
515571f87433Sdalcinl   for computing relative tolerance for linear solvers within an
515671f87433Sdalcinl   inexact Newton method.
515771f87433Sdalcinl 
515871f87433Sdalcinl   Not Collective
515971f87433Sdalcinl 
516071f87433Sdalcinl   Input Parameter:
5161f6dfbefdSBarry Smith . snes - `SNES` context
516271f87433Sdalcinl 
516371f87433Sdalcinl   Output Parameter:
5164f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
516571f87433Sdalcinl 
516671f87433Sdalcinl   Level: advanced
516771f87433Sdalcinl 
51681cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
516971f87433Sdalcinl @*/
5170d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5171d71ae5a4SJacob Faibussowitsch {
517271f87433Sdalcinl   PetscFunctionBegin;
51730700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51744f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
517571f87433Sdalcinl   *flag = snes->ksp_ewconv;
51763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
517771f87433Sdalcinl }
517871f87433Sdalcinl 
517971f87433Sdalcinl /*@
5180fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
518171f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
518271f87433Sdalcinl   Newton method.
518371f87433Sdalcinl 
5184c3339decSBarry Smith   Logically Collective
518571f87433Sdalcinl 
518671f87433Sdalcinl   Input Parameters:
5187f6dfbefdSBarry Smith + snes      - `SNES` context
51880f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
518971f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
519071f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
519171f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
519271f87433Sdalcinl              (0 <= gamma2 <= 1)
519371f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
519471f87433Sdalcinl . alpha2    - power for safeguard
519571f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
519671f87433Sdalcinl 
5197dc4c0fb0SBarry Smith   Level: advanced
5198dc4c0fb0SBarry Smith 
5199f6dfbefdSBarry Smith   Notes:
520071f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
520171f87433Sdalcinl 
5202f6dfbefdSBarry Smith   Use `PETSC_DEFAULT` to retain the default for any of the parameters.
520371f87433Sdalcinl 
52041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
520571f87433Sdalcinl @*/
5206d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5207d71ae5a4SJacob Faibussowitsch {
5208fa9f3622SBarry Smith   SNESKSPEW *kctx;
52095fd66863SKarl Rupp 
521071f87433Sdalcinl   PetscFunctionBegin;
52110700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5212fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52135f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5214c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5215c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5216c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5217c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5218c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5219c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5220c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
522171f87433Sdalcinl 
522271f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
522313bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
522413bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
522513bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
522613bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
522713bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
522813bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
522971f87433Sdalcinl 
52300f0abf79SStefano 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);
52310b121fc5SBarry 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);
52320b121fc5SBarry 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);
52330b121fc5SBarry 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);
52340b121fc5SBarry 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);
52350b121fc5SBarry 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);
52363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
523771f87433Sdalcinl }
523871f87433Sdalcinl 
523971f87433Sdalcinl /*@
5240fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
524171f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
524271f87433Sdalcinl   Newton method.
524371f87433Sdalcinl 
524471f87433Sdalcinl   Not Collective
524571f87433Sdalcinl 
524697bb3fdcSJose E. Roman   Input Parameter:
5247f6dfbefdSBarry Smith . snes - `SNES` context
524871f87433Sdalcinl 
524971f87433Sdalcinl   Output Parameters:
52500f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
525171f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
525271f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5253bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
525471f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
525571f87433Sdalcinl . alpha2    - power for safeguard
525671f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
525771f87433Sdalcinl 
525871f87433Sdalcinl   Level: advanced
525971f87433Sdalcinl 
52601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
526171f87433Sdalcinl @*/
5262d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5263d71ae5a4SJacob Faibussowitsch {
5264fa9f3622SBarry Smith   SNESKSPEW *kctx;
52655fd66863SKarl Rupp 
526671f87433Sdalcinl   PetscFunctionBegin;
52670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5268fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52695f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
527071f87433Sdalcinl   if (version) *version = kctx->version;
527171f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
527271f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
527371f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
527471f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
527571f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
527671f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
52773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
527871f87433Sdalcinl }
527971f87433Sdalcinl 
52805c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5281d71ae5a4SJacob Faibussowitsch {
52825c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5283fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
528471f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
528571f87433Sdalcinl 
528671f87433Sdalcinl   PetscFunctionBegin;
52873ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
528830058271SDmitry Karpeev   if (!snes->iter) {
528930058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
52909566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
52910f0abf79SStefano Zampini   } else {
52920fdf79fbSJacob 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);
529371f87433Sdalcinl     if (kctx->version == 1) {
52940f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
529585ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
529671f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
529771f87433Sdalcinl     } else if (kctx->version == 2) {
529885ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
529985ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
530071f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
530171f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
530285ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
530371f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
530485ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
530571f87433Sdalcinl       stol = PetscMax(rtol, stol);
530671f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
530771f87433Sdalcinl       /* safeguard: avoid oversolving */
530830058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
530971f87433Sdalcinl       stol = PetscMax(rtol, stol);
531071f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
53110fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
53120fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
53130f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
53140f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
53150f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
53160f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
53170f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
53180f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
53190f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
53200f0abf79SStefano Zampini 
5321a4598233SStefano 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;
53220f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
53230f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
53240f0abf79SStefano Zampini       kctx->rk_last     = rk;
53250fdf79fbSJacob Faibussowitsch     }
53260f0abf79SStefano Zampini   }
53270f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
532871f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
53299566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
533063a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
53313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
533271f87433Sdalcinl }
533371f87433Sdalcinl 
53345c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5335d71ae5a4SJacob Faibussowitsch {
53365c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5337fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
533871f87433Sdalcinl   PCSide     pcside;
533971f87433Sdalcinl   Vec        lres;
534071f87433Sdalcinl 
534171f87433Sdalcinl   PetscFunctionBegin;
53423ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
53439566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
534471dbe336SPeter Brune   kctx->norm_last = snes->norm;
53450f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
53464f00ce20SMatthew G. Knepley     PC        pc;
53470f0abf79SStefano Zampini     PetscBool getRes;
53484f00ce20SMatthew G. Knepley 
53499566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
53500f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
53510f0abf79SStefano Zampini     if (!getRes) {
53520f0abf79SStefano Zampini       KSPNormType normtype;
53530f0abf79SStefano Zampini 
53540f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
53550f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
53560f0abf79SStefano Zampini     }
53579566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
53580f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
53599566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
536071f87433Sdalcinl     } else {
536171f87433Sdalcinl       /* KSP residual is preconditioned residual */
536271f87433Sdalcinl       /* compute true linear residual norm */
53630f0abf79SStefano Zampini       Mat J;
53640f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
53659566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
53660f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
53679566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
53689566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
53699566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
537071f87433Sdalcinl     }
537171f87433Sdalcinl   }
53723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
537371f87433Sdalcinl }
537471f87433Sdalcinl 
5375d4211eb9SBarry Smith /*@
5376f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5377d4211eb9SBarry Smith 
5378*420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5379d4211eb9SBarry Smith 
5380d4211eb9SBarry Smith   Input Parameter:
5381f6dfbefdSBarry Smith . snes - the `SNES` context
5382d4211eb9SBarry Smith 
5383d4211eb9SBarry Smith   Output Parameter:
5384f6dfbefdSBarry Smith . ksp - the `KSP` context
5385d4211eb9SBarry Smith 
5386dc4c0fb0SBarry Smith   Level: beginner
5387dc4c0fb0SBarry Smith 
5388d4211eb9SBarry Smith   Notes:
5389f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5390d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5391f6dfbefdSBarry Smith   `PC` contexts as well.
5392f6dfbefdSBarry Smith 
5393f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5394d4211eb9SBarry Smith 
53951cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5396d4211eb9SBarry Smith @*/
5397d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5398d71ae5a4SJacob Faibussowitsch {
539971f87433Sdalcinl   PetscFunctionBegin;
5400d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54014f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5402d4211eb9SBarry Smith 
5403d4211eb9SBarry Smith   if (!snes->ksp) {
54049566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
54059566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5406d4211eb9SBarry Smith 
54075c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
54085c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5409a5c2985bSBarry Smith 
54109566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
54119566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5412d4211eb9SBarry Smith   }
5413d4211eb9SBarry Smith   *ksp = snes->ksp;
54143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
541571f87433Sdalcinl }
54166c699258SBarry Smith 
5417af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
54186c699258SBarry Smith /*@
5419f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
54206c699258SBarry Smith 
5421c3339decSBarry Smith   Logically Collective
54226c699258SBarry Smith 
54236c699258SBarry Smith   Input Parameters:
54242a808120SBarry Smith + snes - the nonlinear solver context
5425*420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5426dc4c0fb0SBarry Smith 
5427dc4c0fb0SBarry Smith   Level: intermediate
54286c699258SBarry Smith 
5429f6dfbefdSBarry Smith   Note:
5430f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5431f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5432e03a659cSJed Brown   problems using the same function space.
5433e03a659cSJed Brown 
5434*420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
54356c699258SBarry Smith @*/
5436d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5437d71ae5a4SJacob Faibussowitsch {
5438345fed2cSBarry Smith   KSP    ksp;
5439942e3340SBarry Smith   DMSNES sdm;
54406c699258SBarry Smith 
54416c699258SBarry Smith   PetscFunctionBegin;
54420700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54432a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
54449566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5445942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
544651f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
54479566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
54489566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5449f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
54506cab3a1bSJed Brown     }
54519566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
54529566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
54536cab3a1bSJed Brown   }
54546c699258SBarry Smith   snes->dm     = dm;
5455116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5456f5af7f23SKarl Rupp 
54579566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
54589566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
54599566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5460efd4aadfSBarry Smith   if (snes->npc) {
54619566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
54629566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
54632c155ee1SBarry Smith   }
54643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54656c699258SBarry Smith }
54666c699258SBarry Smith 
54676c699258SBarry Smith /*@
5468*420bcc1bSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners
54696c699258SBarry Smith 
5470f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
54716c699258SBarry Smith 
54726c699258SBarry Smith   Input Parameter:
5473*420bcc1bSBarry Smith . snes - the `SNES` context
54746c699258SBarry Smith 
54756c699258SBarry Smith   Output Parameter:
5476*420bcc1bSBarry Smith . dm - the `DM`
54776c699258SBarry Smith 
54786c699258SBarry Smith   Level: intermediate
54796c699258SBarry Smith 
5480*420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
54816c699258SBarry Smith @*/
5482d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5483d71ae5a4SJacob Faibussowitsch {
54846c699258SBarry Smith   PetscFunctionBegin;
54850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54866cab3a1bSJed Brown   if (!snes->dm) {
54879566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5488116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
54896cab3a1bSJed Brown   }
54906c699258SBarry Smith   *dm = snes->dm;
54913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54926c699258SBarry Smith }
54930807856dSBarry Smith 
549431823bd8SMatthew G Knepley /*@
5495be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
549631823bd8SMatthew G Knepley 
5497c3339decSBarry Smith   Collective
549831823bd8SMatthew G Knepley 
549931823bd8SMatthew G Knepley   Input Parameters:
5500f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5501*420bcc1bSBarry Smith - npc  - the nonlinear preconditioner object
550231823bd8SMatthew G Knepley 
5503dc4c0fb0SBarry Smith   Level: developer
5504dc4c0fb0SBarry Smith 
550531823bd8SMatthew G Knepley   Notes:
5506f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
550731823bd8SMatthew G Knepley   to configure it using the API).
550831823bd8SMatthew G Knepley 
5509f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5510f6dfbefdSBarry Smith 
5511*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
551231823bd8SMatthew G Knepley @*/
5513d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5514d71ae5a4SJacob Faibussowitsch {
551531823bd8SMatthew G Knepley   PetscFunctionBegin;
551631823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5517f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5518f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5519f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
55209566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5521f6dfbefdSBarry Smith   snes->npc = npc;
55223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
552331823bd8SMatthew G Knepley }
552431823bd8SMatthew G Knepley 
552531823bd8SMatthew G Knepley /*@
5526f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
552731823bd8SMatthew G Knepley 
5528f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
552931823bd8SMatthew G Knepley 
553031823bd8SMatthew G Knepley   Input Parameter:
5531f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
553231823bd8SMatthew G Knepley 
553331823bd8SMatthew G Knepley   Output Parameter:
5534e4094ef1SJacob Faibussowitsch . pc - preconditioner context
553531823bd8SMatthew G Knepley 
5536f6dfbefdSBarry Smith   Options Database Key:
5537f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5538b5badacbSBarry Smith 
5539dc4c0fb0SBarry Smith   Level: developer
5540dc4c0fb0SBarry Smith 
554195452b02SPatrick Sanan   Notes:
5542f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5543be95d8f1SBarry Smith 
5544f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5545f6dfbefdSBarry Smith   `SNES`
5546951fe5abSBarry Smith 
55471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
554831823bd8SMatthew G Knepley @*/
5549d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5550d71ae5a4SJacob Faibussowitsch {
5551a64e098fSPeter Brune   const char *optionsprefix;
555231823bd8SMatthew G Knepley 
555331823bd8SMatthew G Knepley   PetscFunctionBegin;
555431823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55554f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5556efd4aadfSBarry Smith   if (!snes->npc) {
5557ec785e5bSStefano Zampini     void *ctx;
5558ec785e5bSStefano Zampini 
55599566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
55609566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
55619566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
55629566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
55639566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5564ec785e5bSStefano Zampini     PetscCall(SNESGetApplicationContext(snes, &ctx));
5565ec785e5bSStefano Zampini     PetscCall(SNESSetApplicationContext(snes->npc, ctx));
55669566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
556731823bd8SMatthew G Knepley   }
5568efd4aadfSBarry Smith   *pc = snes->npc;
55693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
557031823bd8SMatthew G Knepley }
557131823bd8SMatthew G Knepley 
55723ad1a0b9SPatrick Farrell /*@
55733ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
55743ad1a0b9SPatrick Farrell 
55753ad1a0b9SPatrick Farrell   Not Collective
55763ad1a0b9SPatrick Farrell 
55773ad1a0b9SPatrick Farrell   Input Parameter:
5578f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
55793ad1a0b9SPatrick Farrell 
55803ad1a0b9SPatrick Farrell   Output Parameter:
5581*420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
55823ad1a0b9SPatrick Farrell 
55833ad1a0b9SPatrick Farrell   Level: developer
55843ad1a0b9SPatrick Farrell 
55851cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
55863ad1a0b9SPatrick Farrell @*/
5587d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5588d71ae5a4SJacob Faibussowitsch {
55893ad1a0b9SPatrick Farrell   PetscFunctionBegin;
55903ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5591efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
55923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55933ad1a0b9SPatrick Farrell }
55943ad1a0b9SPatrick Farrell 
5595c40d0f55SPeter Brune /*@
5596*420bcc1bSBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side.
5597c40d0f55SPeter Brune 
5598c3339decSBarry Smith   Logically Collective
5599c40d0f55SPeter Brune 
5600c40d0f55SPeter Brune   Input Parameter:
5601f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5602c40d0f55SPeter Brune 
5603c40d0f55SPeter Brune   Output Parameter:
5604c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5605c40d0f55SPeter Brune .vb
56062d547940SBarry Smith       PC_LEFT - left preconditioning
56072d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5608c40d0f55SPeter Brune .ve
5609c40d0f55SPeter Brune 
5610f6dfbefdSBarry Smith   Options Database Key:
561167b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5612c40d0f55SPeter Brune 
5613dc4c0fb0SBarry Smith   Level: intermediate
5614dc4c0fb0SBarry Smith 
5615f6dfbefdSBarry Smith   Note:
5616f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
56172d547940SBarry Smith 
5618*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5619c40d0f55SPeter Brune @*/
5620d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5621d71ae5a4SJacob Faibussowitsch {
5622c40d0f55SPeter Brune   PetscFunctionBegin;
5623c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5624c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5625b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
562654c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5627efd4aadfSBarry Smith   snes->npcside = side;
56283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5629c40d0f55SPeter Brune }
5630c40d0f55SPeter Brune 
5631c40d0f55SPeter Brune /*@
5632be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5633c40d0f55SPeter Brune 
5634c40d0f55SPeter Brune   Not Collective
5635c40d0f55SPeter Brune 
5636c40d0f55SPeter Brune   Input Parameter:
5637f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5638c40d0f55SPeter Brune 
5639c40d0f55SPeter Brune   Output Parameter:
5640c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5641c40d0f55SPeter Brune .vb
5642f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5643f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5644c40d0f55SPeter Brune .ve
5645c40d0f55SPeter Brune 
5646c40d0f55SPeter Brune   Level: intermediate
5647c40d0f55SPeter Brune 
5648*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5649c40d0f55SPeter Brune @*/
5650d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5651d71ae5a4SJacob Faibussowitsch {
5652c40d0f55SPeter Brune   PetscFunctionBegin;
5653c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56544f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5655efd4aadfSBarry Smith   *side = snes->npcside;
56563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5657c40d0f55SPeter Brune }
5658c40d0f55SPeter Brune 
56599e764e56SPeter Brune /*@
5660*420bcc1bSBarry Smith   SNESSetLineSearch - Sets the linesearch to be used for `SNES`
56619e764e56SPeter Brune 
5662c3339decSBarry Smith   Collective
56639e764e56SPeter Brune 
56649e764e56SPeter Brune   Input Parameters:
5665f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
56669e764e56SPeter Brune - linesearch - the linesearch object
56679e764e56SPeter Brune 
5668dc4c0fb0SBarry Smith   Level: developer
5669dc4c0fb0SBarry Smith 
5670f6dfbefdSBarry Smith   Note:
5671*420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
56729e764e56SPeter Brune   to configure it using the API).
56739e764e56SPeter Brune 
5674*420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
56759e764e56SPeter Brune @*/
5676d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5677d71ae5a4SJacob Faibussowitsch {
56789e764e56SPeter Brune   PetscFunctionBegin;
56799e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5680f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
56819e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
56829566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
56839566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5684f5af7f23SKarl Rupp 
56859e764e56SPeter Brune   snes->linesearch = linesearch;
5686f5af7f23SKarl Rupp 
56873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56889e764e56SPeter Brune }
56899e764e56SPeter Brune 
5690a34ceb2aSJed Brown /*@
5691*420bcc1bSBarry Smith   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5692f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
56939e764e56SPeter Brune 
56949e764e56SPeter Brune   Not Collective
56959e764e56SPeter Brune 
56969e764e56SPeter Brune   Input Parameter:
5697f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56989e764e56SPeter Brune 
56999e764e56SPeter Brune   Output Parameter:
57009e764e56SPeter Brune . linesearch - linesearch context
57019e764e56SPeter Brune 
5702162e0bf5SPeter Brune   Level: beginner
57039e764e56SPeter Brune 
57041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
57059e764e56SPeter Brune @*/
5706d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5707d71ae5a4SJacob Faibussowitsch {
57089e764e56SPeter Brune   const char *optionsprefix;
57099e764e56SPeter Brune 
57109e764e56SPeter Brune   PetscFunctionBegin;
57119e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57124f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
57139e764e56SPeter Brune   if (!snes->linesearch) {
57149566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57159566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
57169566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
57179566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
57189566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
57199e764e56SPeter Brune   }
57209e764e56SPeter Brune   *linesearch = snes->linesearch;
57213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57229e764e56SPeter Brune }
5723