xref: /petsc/src/snes/interface/snes.c (revision ffeef943c8ee50edff320d8a3135bb0c94853e4c)
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 
83420bcc1bSBarry 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 
106420bcc1bSBarry 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 
1358434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `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 
1658434afd1SBarry Smith .seealso: [](ch_snes), `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `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
179420bcc1bSBarry 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 
1928434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `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 /*@
203420bcc1bSBarry 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:
211420bcc1bSBarry 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 
2158434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSetFunction()`, `SNESFunctionFn`, `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 /*@
227420bcc1bSBarry 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 /*@
251420bcc1bSBarry 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 
274*ffeef943SBarry Smith /*@
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:
287420bcc1bSBarry 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 
324*ffeef943SBarry Smith /*@
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 
348*ffeef943SBarry Smith /*@
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;
4088434afd1SBarry Smith     SNESJacobianFn  *cJ;
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 
562420bcc1bSBarry Smith   Calling sequence of `snescheck`:
563420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
564420bcc1bSBarry Smith 
56576b2cf59SMatthew Knepley   Level: developer
56676b2cf59SMatthew Knepley 
5671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
56876b2cf59SMatthew Knepley @*/
569420bcc1bSBarry 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;
6878434afd1SBarry Smith   SNESJacobianFn *jac = 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 
72973a84a35SBarry Smith   Developer Note:
73073a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
73173a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
73273a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
73373a84a35SBarry Smith 
7341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7356cab3a1bSJed Brown @*/
736d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
737d71ae5a4SJacob Faibussowitsch {
7386cab3a1bSJed Brown   DM     dm;
739942e3340SBarry Smith   DMSNES sdm;
7406cab3a1bSJed Brown 
7416cab3a1bSJed Brown   PetscFunctionBegin;
7429566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7439566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
74473a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7456cab3a1bSJed Brown     Mat   J;
7466cab3a1bSJed Brown     void *functx;
7479566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7489566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7499566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7509566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7519566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7529566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
753caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7546cab3a1bSJed Brown     Mat J, B;
7559566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7569566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7579566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7589566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
75906f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7609566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7619566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7629566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
763caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7641ba9b98eSMatthew G. Knepley     PetscDS   prob;
7656cab3a1bSJed Brown     Mat       J, B;
7661ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7671ba9b98eSMatthew G. Knepley 
7686cab3a1bSJed Brown     J = snes->jacobian;
7699566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7709566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7719566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7729566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7739566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7749566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7769566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7776cab3a1bSJed Brown   }
778caa4e7f2SJed Brown   {
779caa4e7f2SJed Brown     KSP ksp;
7809566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
7819566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
7829566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
783caa4e7f2SJed Brown   }
7843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7856cab3a1bSJed Brown }
7866cab3a1bSJed Brown 
787d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
788d71ae5a4SJacob Faibussowitsch {
7895e7c47f3SMatthew G. Knepley   PetscInt i;
7905e7c47f3SMatthew G. Knepley 
7915e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
7923ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
7935e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
7945e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
7955e7c47f3SMatthew G. Knepley     PetscDraw             draw;
7965e7c47f3SMatthew G. Knepley     PetscReal             lpause;
7975e7c47f3SMatthew G. Knepley 
7985e7c47f3SMatthew G. Knepley     if (!vf) continue;
7995e7c47f3SMatthew G. Knepley     if (vf->lg) {
8005e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
8015e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
8029566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
8039566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8049566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8059566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8069566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8075e7c47f3SMatthew G. Knepley     } else {
8085e7c47f3SMatthew G. Knepley       PetscBool isdraw;
8095e7c47f3SMatthew G. Knepley 
8105e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
8115e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
8129566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
8135e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
8149566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
8159566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8169566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8179566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8189566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8195e7c47f3SMatthew G. Knepley     }
8205e7c47f3SMatthew G. Knepley   }
8213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8225e7c47f3SMatthew G. Knepley }
8235e7c47f3SMatthew G. Knepley 
824fde5950dSBarry Smith /*@C
825fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
826fde5950dSBarry Smith 
827c3339decSBarry Smith   Collective
828fde5950dSBarry Smith 
829fde5950dSBarry Smith   Input Parameters:
830dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
831fde5950dSBarry Smith . name         - the monitor type one is seeking
832fde5950dSBarry Smith . help         - message indicating what monitoring is done
833fde5950dSBarry Smith . manual       - manual page for the monitor
834fde5950dSBarry Smith . monitor      - the monitor function
835f6dfbefdSBarry 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
836fde5950dSBarry Smith 
837420bcc1bSBarry Smith   Calling sequence of `monitor`:
838420bcc1bSBarry Smith + snes - the nonlinear solver context
839420bcc1bSBarry Smith . it   - the current iteration
840420bcc1bSBarry Smith . r    - the current function norm
841420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
842420bcc1bSBarry Smith 
843420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
844420bcc1bSBarry Smith + snes - the nonlinear solver context
845420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
846420bcc1bSBarry Smith 
847f6dfbefdSBarry Smith   Options Database Key:
848f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
849f6dfbefdSBarry Smith 
850f6dfbefdSBarry Smith   Level: advanced
851fde5950dSBarry Smith 
8521cc06b55SBarry Smith .seealso: [](ch_snes), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
853db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
854e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
855db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
856c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
857db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
858db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
859fde5950dSBarry Smith @*/
860420bcc1bSBarry 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))
861d71ae5a4SJacob Faibussowitsch {
862fde5950dSBarry Smith   PetscViewer       viewer;
863fde5950dSBarry Smith   PetscViewerFormat format;
864fde5950dSBarry Smith   PetscBool         flg;
865fde5950dSBarry Smith 
866fde5950dSBarry Smith   PetscFunctionBegin;
8679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
868fde5950dSBarry Smith   if (flg) {
869d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8709566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
871cd791dc2SBarry Smith     PetscCall(PetscOptionsRestoreViewer(&viewer));
8721baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
8739566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
874fde5950dSBarry Smith   }
8753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
876fde5950dSBarry Smith }
877fde5950dSBarry Smith 
878a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
879d71ae5a4SJacob Faibussowitsch {
880a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
881a4598233SStefano Zampini 
8820f0abf79SStefano Zampini   PetscFunctionBegin;
8830f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
884a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
885a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
886a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
887a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
888a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
889a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
8900f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
891a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
8920f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
8930f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
8940f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
8950f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
8960f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
8970f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
8980f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
8990f0abf79SStefano Zampini   PetscOptionsEnd();
9003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9010f0abf79SStefano Zampini }
9020f0abf79SStefano Zampini 
9039b94acceSBarry Smith /*@
904f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9059b94acceSBarry Smith 
906c3339decSBarry Smith   Collective
907c7afd0dbSLois Curfman McInnes 
9089b94acceSBarry Smith   Input Parameter:
909f6dfbefdSBarry Smith . snes - the `SNES` context
9109b94acceSBarry Smith 
91136851e7fSLois Curfman McInnes   Options Database Keys:
912f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
913ceaaa498SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
91470441072SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
915b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
916e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
917ceaaa498SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
918b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
919b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
9204839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
921ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
922a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9233d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
924e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9253d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
9264a221d59SStefano Zampini . -snes_tr_tol <trtol>                                                         - trust region tolerance
927ceaaa498SBarry 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.
928fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
929fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
930fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
931fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9324619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
933459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9345e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
935e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
936e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
937ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
938b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
939ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
940e62ac41dSBarry 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.
941e62ac41dSBarry 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.
94282738288SBarry Smith 
943f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
944fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9454b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
94636851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
94736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
94836851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
94936851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
95036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
95136851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
95282738288SBarry Smith 
953dc4c0fb0SBarry Smith   Level: beginner
954dc4c0fb0SBarry Smith 
95511ca99fdSLois Curfman McInnes   Notes:
956ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
957ec5066bdSBarry Smith 
958420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
959420bcc1bSBarry Smith   and computing explicitly with
960f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
96183e2fdc7SBarry Smith 
962420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9639b94acceSBarry Smith @*/
964d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
965d71ae5a4SJacob Faibussowitsch {
9668afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
967d8f46077SPeter Brune   PetscInt    i, indx, lag, grids;
96804d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
969649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
97085385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9710f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
972c40d0f55SPeter Brune   PCSide      pcside;
973a64e098fSPeter Brune   const char *optionsprefix;
9749b94acceSBarry Smith 
9753a40ed3dSBarry Smith   PetscFunctionBegin;
9760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9779566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
978d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
979639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
9809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
981d64ed03dSBarry Smith   if (flg) {
9829566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
9837adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
9849566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
985d64ed03dSBarry Smith   }
9869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &snes->stol, NULL));
9879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &snes->abstol, NULL));
988186905e3SBarry Smith 
9899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &snes->rtol, NULL));
9909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, NULL));
9919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &snes->max_its, NULL));
9929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &snes->max_funcs, NULL));
9939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, NULL));
9949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, NULL));
9959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
9969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
9979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
99885385478SLisandro Dalcin 
9999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1000a8054027SBarry Smith   if (flg) {
10015f80ce2aSJacob 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");
10029566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1003a8054027SBarry Smith   }
10049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10051baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1007e35cf81dSBarry Smith   if (flg) {
10085f80ce2aSJacob 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");
10099566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1010e35cf81dSBarry Smith   }
10119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10121baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
101337ec4e1aSPeter Brune 
10149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10151baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1016a8054027SBarry Smith 
1017400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
101885385478SLisandro Dalcin   if (flg) {
101985385478SLisandro Dalcin     switch (indx) {
1020d71ae5a4SJacob Faibussowitsch     case 0:
1021d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1022d71ae5a4SJacob Faibussowitsch       break;
1023d71ae5a4SJacob Faibussowitsch     case 1:
1024d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1025d71ae5a4SJacob Faibussowitsch       break;
1026d71ae5a4SJacob Faibussowitsch     case 2:
1027d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1028d71ae5a4SJacob Faibussowitsch       break;
102985385478SLisandro Dalcin     }
103085385478SLisandro Dalcin   }
103185385478SLisandro Dalcin 
10329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10339566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1034fdacfa88SPeter Brune 
10359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10369566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1037186905e3SBarry Smith 
103885385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
103985385478SLisandro Dalcin 
10409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1041186905e3SBarry Smith 
10420f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10430f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1044a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1045186905e3SBarry Smith 
104690d69ab7SBarry Smith   flg = PETSC_FALSE;
10479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10489566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1049eabae89aSBarry Smith 
10509566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10519566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10529566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1053eabae89aSBarry Smith 
10549566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10559566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10569566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10579566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10589566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10599566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10609566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10622db13446SMatthew G. Knepley 
10639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10649566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10655180491cSLisandro Dalcin 
106690d69ab7SBarry Smith   flg = PETSC_FALSE;
10679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1068459f5d12SBarry Smith   if (flg) {
1069459f5d12SBarry Smith     PetscViewer ctx;
1070e24b481bSBarry Smith 
10719566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
10729566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode(*)(void **))PetscViewerDestroy));
1073459f5d12SBarry Smith   }
10742e7541e6SPeter Brune 
107590d69ab7SBarry Smith   flg = PETSC_FALSE;
10769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
10779566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1078c4421ceaSFande Kong 
1079c4421ceaSFande Kong   flg = PETSC_FALSE;
10809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
10814b27c08aSLois Curfman McInnes   if (flg) {
10826cab3a1bSJed Brown     void *functx;
1083b1f624c7SBarry Smith     DM    dm;
10849566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1085800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
10869566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
10879566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
10889566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
10899b94acceSBarry Smith   }
1090639f9d9dSBarry Smith 
109144848bc4SPeter Brune   flg = PETSC_FALSE;
10929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
10931baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
109497584545SPeter Brune 
109597584545SPeter Brune   flg = PETSC_FALSE;
10969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
109744848bc4SPeter Brune   if (flg) {
1098c52e227fSPeter Brune     DM dm;
10999566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1100800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11019566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11029566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
110344848bc4SPeter Brune   }
110444848bc4SPeter Brune 
1105aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1107d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1108a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1109d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1110a8248277SBarry Smith   }
1111aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1113d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1115d28543b3SPeter Brune 
1116c40d0f55SPeter Brune   flg = PETSC_FALSE;
11179566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11199566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1120c40d0f55SPeter Brune 
1121e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11228a70d858SHong Zhang   /*
11238a70d858SHong Zhang     Publish convergence information using SAWs
11248a70d858SHong Zhang   */
11258a70d858SHong Zhang   flg = PETSC_FALSE;
11269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11278a70d858SHong Zhang   if (flg) {
11288a70d858SHong Zhang     void *ctx;
11299566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11309566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11318a70d858SHong Zhang   }
11328a70d858SHong Zhang #endif
11338a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1134b90c6cbeSBarry Smith   {
1135b90c6cbeSBarry Smith     PetscBool set;
1136b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11379566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11381baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1139b90c6cbeSBarry Smith   }
1140b90c6cbeSBarry Smith #endif
1141b90c6cbeSBarry Smith 
114248a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
114376b2cf59SMatthew Knepley 
1144dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11455d973c19SBarry Smith 
11465d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1147dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1148d0609cedSBarry Smith   PetscOptionsEnd();
11494bbc92c1SBarry Smith 
1150d8d34be6SBarry Smith   if (snes->linesearch) {
11519566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11529566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1153d8d34be6SBarry Smith   }
11549e764e56SPeter Brune 
11556aa5e7e9SBarry Smith   if (snes->usesksp) {
11569566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11579566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11589566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11596aa5e7e9SBarry Smith   }
11606991f827SBarry Smith 
1161b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11629566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
116448a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
11651baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1166b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
11673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1168b3cd9a81SMatthew G. Knepley }
1169b3cd9a81SMatthew G. Knepley 
1170b3cd9a81SMatthew G. Knepley /*@
1171420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1172b3cd9a81SMatthew G. Knepley 
1173c3339decSBarry Smith   Collective
1174b3cd9a81SMatthew G. Knepley 
1175b3cd9a81SMatthew G. Knepley   Input Parameter:
1176f6dfbefdSBarry Smith . snes - the `SNES` context
1177b3cd9a81SMatthew G. Knepley 
1178420bcc1bSBarry Smith   Level: advanced
1179b3cd9a81SMatthew G. Knepley 
11801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1181b3cd9a81SMatthew G. Knepley @*/
1182d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1183d71ae5a4SJacob Faibussowitsch {
1184b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
11859566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
11863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11879b94acceSBarry Smith }
11889b94acceSBarry Smith 
1189bb9467b5SJed Brown /*@C
1190d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1191d25893d9SBarry Smith   the nonlinear solvers.
1192d25893d9SBarry Smith 
1193dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1194d25893d9SBarry Smith 
1195d25893d9SBarry Smith   Input Parameters:
1196f6dfbefdSBarry Smith + snes    - the `SNES` context
1197d25893d9SBarry Smith . compute - function to compute the context
1198d25893d9SBarry Smith - destroy - function to destroy the context
1199d25893d9SBarry Smith 
1200420bcc1bSBarry Smith   Calling sequence of `compute`:
1201420bcc1bSBarry Smith + snes - the `SNES` context
1202420bcc1bSBarry Smith - ctx  - context to be computed
1203420bcc1bSBarry Smith 
1204420bcc1bSBarry Smith   Calling sequence of `destroy`:
1205420bcc1bSBarry Smith . ctx - context to be computed by `compute()`
1206420bcc1bSBarry Smith 
1207d25893d9SBarry Smith   Level: intermediate
1208d25893d9SBarry Smith 
1209f6dfbefdSBarry Smith   Note:
1210f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1211f6dfbefdSBarry Smith 
1212f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1213f6dfbefdSBarry Smith 
121442747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`
1215d25893d9SBarry Smith @*/
1216420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx))
1217d71ae5a4SJacob Faibussowitsch {
1218d25893d9SBarry Smith   PetscFunctionBegin;
1219d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1220d25893d9SBarry Smith   snes->ops->usercompute = compute;
1221d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
12223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1223d25893d9SBarry Smith }
1224a847f771SSatish Balay 
1225b07ff414SBarry Smith /*@
1226f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12279b94acceSBarry Smith 
1228c3339decSBarry Smith   Logically Collective
1229fee21e36SBarry Smith 
1230c7afd0dbSLois Curfman McInnes   Input Parameters:
1231f6dfbefdSBarry Smith + snes - the `SNES` context
1232c7afd0dbSLois Curfman McInnes - usrP - optional user context
1233c7afd0dbSLois Curfman McInnes 
123436851e7fSLois Curfman McInnes   Level: intermediate
123536851e7fSLois Curfman McInnes 
1236f6dfbefdSBarry Smith   Notes:
1237f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1238f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1239f6dfbefdSBarry Smith 
1240f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1241f6dfbefdSBarry Smith 
1242420bcc1bSBarry Smith   Fortran Note:
1243dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1244420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1245daf670e6SBarry Smith 
12461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12479b94acceSBarry Smith @*/
1248d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1249d71ae5a4SJacob Faibussowitsch {
1250b07ff414SBarry Smith   KSP ksp;
12511b2093e4SBarry Smith 
12523a40ed3dSBarry Smith   PetscFunctionBegin;
12530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12549566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12559566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12569b94acceSBarry Smith   snes->user = usrP;
12573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12589b94acceSBarry Smith }
125974679c65SBarry Smith 
1260b07ff414SBarry Smith /*@
12619b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1262420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12639b94acceSBarry Smith 
1264c7afd0dbSLois Curfman McInnes   Not Collective
1265c7afd0dbSLois Curfman McInnes 
12669b94acceSBarry Smith   Input Parameter:
1267f6dfbefdSBarry Smith . snes - `SNES` context
12689b94acceSBarry Smith 
12699b94acceSBarry Smith   Output Parameter:
12709b94acceSBarry Smith . usrP - user context
12719b94acceSBarry Smith 
127236851e7fSLois Curfman McInnes   Level: intermediate
127336851e7fSLois Curfman McInnes 
1274420bcc1bSBarry Smith   Fortran Note:
1275dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1276420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1277dc4c0fb0SBarry Smith 
1278420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
12799b94acceSBarry Smith @*/
1280d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1281d71ae5a4SJacob Faibussowitsch {
12823a40ed3dSBarry Smith   PetscFunctionBegin;
12830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1284e71120c6SJed Brown   *(void **)usrP = snes->user;
12853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12869b94acceSBarry Smith }
128774679c65SBarry Smith 
12889b94acceSBarry Smith /*@
1289420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
12903565c898SBarry Smith 
1291dc4c0fb0SBarry Smith   Logically Collective
12923565c898SBarry Smith 
12933565c898SBarry Smith   Input Parameters:
1294f6dfbefdSBarry Smith + snes        - `SNES` context
1295f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1296f6dfbefdSBarry 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
1297420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
12983565c898SBarry Smith 
1299f6dfbefdSBarry Smith   Options Database Keys:
130001c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1301f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1302ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1303ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13043565c898SBarry Smith 
13053565c898SBarry Smith   Level: intermediate
13063565c898SBarry Smith 
1307f6dfbefdSBarry Smith   Note:
1308420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1309420bcc1bSBarry Smith   and computing explicitly with
1310f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1311ec5066bdSBarry Smith 
1312420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13133565c898SBarry Smith @*/
1314d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1315d71ae5a4SJacob Faibussowitsch {
13163565c898SBarry Smith   PetscFunctionBegin;
13173565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
131888b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
131988b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13204ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13213565c898SBarry Smith   snes->mf_operator = mf_operator;
13223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13233565c898SBarry Smith }
13243565c898SBarry Smith 
13253565c898SBarry Smith /*@
1326dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13273565c898SBarry Smith 
1328420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13293565c898SBarry Smith 
13303565c898SBarry Smith   Input Parameter:
1331f6dfbefdSBarry Smith . snes - `SNES` context
13323565c898SBarry Smith 
13333565c898SBarry Smith   Output Parameters:
1334f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1335f6dfbefdSBarry 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
13363565c898SBarry Smith 
13373565c898SBarry Smith   Level: intermediate
13383565c898SBarry Smith 
13391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13403565c898SBarry Smith @*/
1341d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1342d71ae5a4SJacob Faibussowitsch {
13433565c898SBarry Smith   PetscFunctionBegin;
13443565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13453565c898SBarry Smith   if (mf) *mf = snes->mf;
13463565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13483565c898SBarry Smith }
13493565c898SBarry Smith 
13503565c898SBarry Smith /*@
1351420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13529b94acceSBarry Smith 
1353c7afd0dbSLois Curfman McInnes   Not Collective
1354c7afd0dbSLois Curfman McInnes 
13559b94acceSBarry Smith   Input Parameter:
1356f6dfbefdSBarry Smith . snes - `SNES` context
13579b94acceSBarry Smith 
13589b94acceSBarry Smith   Output Parameter:
13599b94acceSBarry Smith . iter - iteration number
13609b94acceSBarry Smith 
1361dc4c0fb0SBarry Smith   Level: intermediate
1362dc4c0fb0SBarry Smith 
1363c8228a4eSBarry Smith   Notes:
1364c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1365c8228a4eSBarry Smith 
1366c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1367f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
136808405cd6SLois Curfman McInnes .vb
136908405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
137008405cd6SLois Curfman McInnes       if (!(it % 2)) {
137108405cd6SLois Curfman McInnes         [compute Jacobian here]
137208405cd6SLois Curfman McInnes       }
137308405cd6SLois Curfman McInnes .ve
1374f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1375f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1376c8228a4eSBarry Smith 
1377f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1378c04deec6SBarry Smith 
1379420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
13809b94acceSBarry Smith @*/
1381d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1382d71ae5a4SJacob Faibussowitsch {
13833a40ed3dSBarry Smith   PetscFunctionBegin;
13840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13854f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
13869b94acceSBarry Smith   *iter = snes->iter;
13873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13889b94acceSBarry Smith }
138974679c65SBarry Smith 
1390360c497dSPeter Brune /*@
1391360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1392360c497dSPeter Brune 
1393360c497dSPeter Brune   Not Collective
1394360c497dSPeter Brune 
1395d8d19677SJose E. Roman   Input Parameters:
1396f6dfbefdSBarry Smith + snes - `SNES` context
1397a2b725a8SWilliam Gropp - iter - iteration number
1398360c497dSPeter Brune 
1399360c497dSPeter Brune   Level: developer
1400360c497dSPeter Brune 
1401420bcc1bSBarry Smith   Note:
1402420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1403420bcc1bSBarry Smith 
14041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1405360c497dSPeter Brune @*/
1406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1407d71ae5a4SJacob Faibussowitsch {
1408360c497dSPeter Brune   PetscFunctionBegin;
1409360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14109566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1411360c497dSPeter Brune   snes->iter = iter;
14129566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1414360c497dSPeter Brune }
1415360c497dSPeter Brune 
14169b94acceSBarry Smith /*@
1417b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1418420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14199b94acceSBarry Smith 
1420c7afd0dbSLois Curfman McInnes   Not Collective
1421c7afd0dbSLois Curfman McInnes 
14229b94acceSBarry Smith   Input Parameter:
1423f6dfbefdSBarry Smith . snes - `SNES` context
14249b94acceSBarry Smith 
14259b94acceSBarry Smith   Output Parameter:
14269b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14279b94acceSBarry Smith 
1428dc4c0fb0SBarry Smith   Level: intermediate
1429dc4c0fb0SBarry Smith 
1430f6dfbefdSBarry Smith   Note:
1431f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1432c96a6f78SLois Curfman McInnes 
14331cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1434db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14359b94acceSBarry Smith @*/
1436d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1437d71ae5a4SJacob Faibussowitsch {
14383a40ed3dSBarry Smith   PetscFunctionBegin;
14390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14404f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
144150ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
144350ffb88aSMatthew Knepley }
144450ffb88aSMatthew Knepley 
144550ffb88aSMatthew Knepley /*@
1446b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1447420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
144850ffb88aSMatthew Knepley 
144950ffb88aSMatthew Knepley   Not Collective
145050ffb88aSMatthew Knepley 
145150ffb88aSMatthew Knepley   Input Parameters:
1452f6dfbefdSBarry Smith + snes     - `SNES` context
145350ffb88aSMatthew Knepley - maxFails - maximum of unsuccessful steps
145450ffb88aSMatthew Knepley 
1455420bcc1bSBarry Smith   Options Database Key:
1456420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1457420bcc1bSBarry Smith 
145850ffb88aSMatthew Knepley   Level: intermediate
145950ffb88aSMatthew Knepley 
1460420bcc1bSBarry Smith   Developer Note:
1461420bcc1bSBarry Smith   The options database key is wrong for this function name
1462420bcc1bSBarry Smith 
14631cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1464db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
146550ffb88aSMatthew Knepley @*/
1466d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1467d71ae5a4SJacob Faibussowitsch {
146850ffb88aSMatthew Knepley   PetscFunctionBegin;
14690700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
147050ffb88aSMatthew Knepley   snes->maxFailures = maxFails;
14713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147250ffb88aSMatthew Knepley }
147350ffb88aSMatthew Knepley 
147450ffb88aSMatthew Knepley /*@
1475b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1476420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
147750ffb88aSMatthew Knepley 
147850ffb88aSMatthew Knepley   Not Collective
147950ffb88aSMatthew Knepley 
148050ffb88aSMatthew Knepley   Input Parameter:
148120f4b53cSBarry Smith . snes - `SNES` context
148250ffb88aSMatthew Knepley 
148350ffb88aSMatthew Knepley   Output Parameter:
148450ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
148550ffb88aSMatthew Knepley 
148650ffb88aSMatthew Knepley   Level: intermediate
148750ffb88aSMatthew Knepley 
14881cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1489db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
149050ffb88aSMatthew Knepley @*/
1491d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1492d71ae5a4SJacob Faibussowitsch {
149350ffb88aSMatthew Knepley   PetscFunctionBegin;
14940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14954f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
149650ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
14973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14989b94acceSBarry Smith }
1499a847f771SSatish Balay 
15002541af92SBarry Smith /*@
15012541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1502420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15032541af92SBarry Smith 
15042541af92SBarry Smith   Not Collective
15052541af92SBarry Smith 
15062541af92SBarry Smith   Input Parameter:
1507f6dfbefdSBarry Smith . snes - `SNES` context
15082541af92SBarry Smith 
15092541af92SBarry Smith   Output Parameter:
15102541af92SBarry Smith . nfuncs - number of evaluations
15112541af92SBarry Smith 
15122541af92SBarry Smith   Level: intermediate
15132541af92SBarry Smith 
1514f6dfbefdSBarry Smith   Note:
1515f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1516971e163fSPeter Brune 
15171cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15182541af92SBarry Smith @*/
1519d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1520d71ae5a4SJacob Faibussowitsch {
15212541af92SBarry Smith   PetscFunctionBegin;
15220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15234f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15242541af92SBarry Smith   *nfuncs = snes->nfuncs;
15253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15262541af92SBarry Smith }
15272541af92SBarry Smith 
15283d4c4710SBarry Smith /*@
15293d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1530420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15313d4c4710SBarry Smith 
15323d4c4710SBarry Smith   Not Collective
15333d4c4710SBarry Smith 
15343d4c4710SBarry Smith   Input Parameter:
1535f6dfbefdSBarry Smith . snes - `SNES` context
15363d4c4710SBarry Smith 
15373d4c4710SBarry Smith   Output Parameter:
15383d4c4710SBarry Smith . nfails - number of failed solves
15393d4c4710SBarry Smith 
1540f6dfbefdSBarry Smith   Options Database Key:
15419d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15429d85da0cSMatthew G. Knepley 
1543f6dfbefdSBarry Smith   Level: intermediate
1544f6dfbefdSBarry Smith 
1545f6dfbefdSBarry Smith   Note:
1546f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15473d4c4710SBarry Smith 
15481cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15493d4c4710SBarry Smith @*/
1550d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1551d71ae5a4SJacob Faibussowitsch {
15523d4c4710SBarry Smith   PetscFunctionBegin;
15530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15544f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15553d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15573d4c4710SBarry Smith }
15583d4c4710SBarry Smith 
15593d4c4710SBarry Smith /*@
15603d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1561f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
15623d4c4710SBarry Smith 
1563c3339decSBarry Smith   Logically Collective
15643d4c4710SBarry Smith 
15653d4c4710SBarry Smith   Input Parameters:
1566f6dfbefdSBarry Smith + snes     - `SNES` context
15673d4c4710SBarry Smith - maxFails - maximum allowed linear solve failures
15683d4c4710SBarry Smith 
1569f6dfbefdSBarry Smith   Options Database Key:
15709d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15719d85da0cSMatthew G. Knepley 
1572dc4c0fb0SBarry Smith   Level: intermediate
1573dc4c0fb0SBarry Smith 
1574f6dfbefdSBarry Smith   Note:
1575f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
15763d4c4710SBarry Smith 
1577420bcc1bSBarry Smith   Developer Note:
1578420bcc1bSBarry Smith   The options database key is wrong for this function name
1579420bcc1bSBarry Smith 
15801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
15813d4c4710SBarry Smith @*/
1582d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1583d71ae5a4SJacob Faibussowitsch {
15843d4c4710SBarry Smith   PetscFunctionBegin;
15850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1586c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
15873d4c4710SBarry Smith   snes->maxLinearSolveFailures = maxFails;
15883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15893d4c4710SBarry Smith }
15903d4c4710SBarry Smith 
15913d4c4710SBarry Smith /*@
15923d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1593f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
15943d4c4710SBarry Smith 
15953d4c4710SBarry Smith   Not Collective
15963d4c4710SBarry Smith 
15973d4c4710SBarry Smith   Input Parameter:
1598f6dfbefdSBarry Smith . snes - `SNES` context
15993d4c4710SBarry Smith 
16003d4c4710SBarry Smith   Output Parameter:
16013d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16023d4c4710SBarry Smith 
16033d4c4710SBarry Smith   Level: intermediate
16043d4c4710SBarry Smith 
1605f6dfbefdSBarry Smith   Note:
1606f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16073d4c4710SBarry Smith 
16081cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16093d4c4710SBarry Smith @*/
1610d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1611d71ae5a4SJacob Faibussowitsch {
16123d4c4710SBarry Smith   PetscFunctionBegin;
16130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16144f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16153d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16173d4c4710SBarry Smith }
16183d4c4710SBarry Smith 
1619c96a6f78SLois Curfman McInnes /*@
1620b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1621420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1622c96a6f78SLois Curfman McInnes 
1623c7afd0dbSLois Curfman McInnes   Not Collective
1624c7afd0dbSLois Curfman McInnes 
1625c96a6f78SLois Curfman McInnes   Input Parameter:
1626f6dfbefdSBarry Smith . snes - `SNES` context
1627c96a6f78SLois Curfman McInnes 
1628c96a6f78SLois Curfman McInnes   Output Parameter:
1629c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1630c96a6f78SLois Curfman McInnes 
1631dc4c0fb0SBarry Smith   Level: intermediate
1632dc4c0fb0SBarry Smith 
1633c96a6f78SLois Curfman McInnes   Notes:
1634f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1635c96a6f78SLois Curfman McInnes 
1636f6dfbefdSBarry 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
1637f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1638010be392SBarry Smith 
16391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1640c96a6f78SLois Curfman McInnes @*/
1641d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1642d71ae5a4SJacob Faibussowitsch {
16433a40ed3dSBarry Smith   PetscFunctionBegin;
16440700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16454f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1646c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1648c96a6f78SLois Curfman McInnes }
1649c96a6f78SLois Curfman McInnes 
1650971e163fSPeter Brune /*@
1651971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1652f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1653971e163fSPeter Brune 
1654c3339decSBarry Smith   Logically Collective
1655971e163fSPeter Brune 
1656d8d19677SJose E. Roman   Input Parameters:
1657f6dfbefdSBarry Smith + snes  - `SNES` context
1658f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1659971e163fSPeter Brune 
1660971e163fSPeter Brune   Level: developer
1661971e163fSPeter Brune 
16621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1663971e163fSPeter Brune @*/
1664d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1665d71ae5a4SJacob Faibussowitsch {
1666971e163fSPeter Brune   PetscFunctionBegin;
1667971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1668971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1669971e163fSPeter Brune   snes->counters_reset = reset;
16703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1671971e163fSPeter Brune }
1672971e163fSPeter Brune 
16732999313aSBarry Smith /*@
1674f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
16752999313aSBarry Smith 
1676420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
16772999313aSBarry Smith 
16782999313aSBarry Smith   Input Parameters:
1679f6dfbefdSBarry Smith + snes - the `SNES` context
1680f6dfbefdSBarry Smith - ksp  - the `KSP` context
16812999313aSBarry Smith 
1682dc4c0fb0SBarry Smith   Level: developer
1683dc4c0fb0SBarry Smith 
16842999313aSBarry Smith   Notes:
1685f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
16862999313aSBarry Smith   so this routine is rarely needed.
16872999313aSBarry Smith 
1688f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1689420bcc1bSBarry Smith   decreased by one when this is called.
16902999313aSBarry Smith 
169142747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
16922999313aSBarry Smith @*/
1693d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1694d71ae5a4SJacob Faibussowitsch {
16952999313aSBarry Smith   PetscFunctionBegin;
16960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16970700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
16982999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
16999566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17009566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17012999313aSBarry Smith   snes->ksp = ksp;
17023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17032999313aSBarry Smith }
17042999313aSBarry Smith 
170552baeb72SSatish Balay /*@
1706dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
17079b94acceSBarry Smith 
1708d083f849SBarry Smith   Collective
1709c7afd0dbSLois Curfman McInnes 
1710f6dfbefdSBarry Smith   Input Parameter:
1711906ed7ccSBarry Smith . comm - MPI communicator
17129b94acceSBarry Smith 
17139b94acceSBarry Smith   Output Parameter:
171420f4b53cSBarry Smith . outsnes - the new `SNES` context
17159b94acceSBarry Smith 
1716c7afd0dbSLois Curfman McInnes   Options Database Keys:
1717dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1718dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1719dc4c0fb0SBarry Smith                       as set by `SNESSetJacobian()`
1720dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1721c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1722c1f60f51SBarry Smith 
172336851e7fSLois Curfman McInnes   Level: beginner
172436851e7fSLois Curfman McInnes 
172595452b02SPatrick Sanan   Developer Notes:
1726f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1727efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1728f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1729f6dfbefdSBarry Smith   in `SNESView()`.
1730efd4aadfSBarry Smith 
1731f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1732f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1733f6dfbefdSBarry Smith 
1734dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1735efd4aadfSBarry Smith 
1736e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
17379b94acceSBarry Smith @*/
1738d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1739d71ae5a4SJacob Faibussowitsch {
17409b94acceSBarry Smith   SNES       snes;
1741fa9f3622SBarry Smith   SNESKSPEW *kctx;
174237fcc0dbSBarry Smith 
17433a40ed3dSBarry Smith   PetscFunctionBegin;
17444f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
17450298fd71SBarry Smith   *outsnes = NULL;
17469566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
17478ba1e511SMatthew Knepley 
17489566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
17497adad957SLisandro Dalcin 
17508d359177SBarry Smith   snes->ops->converged       = SNESConvergedDefault;
17512c155ee1SBarry Smith   snes->usesksp              = PETSC_TRUE;
175288976e71SPeter Brune   snes->tolerancesset        = PETSC_FALSE;
17539b94acceSBarry Smith   snes->max_its              = 50;
17549750a799SBarry Smith   snes->max_funcs            = 10000;
17559b94acceSBarry Smith   snes->norm                 = 0.0;
1756c1e67a49SFande Kong   snes->xnorm                = 0.0;
1757c1e67a49SFande Kong   snes->ynorm                = 0.0;
1758365a6726SPeter Brune   snes->normschedule         = SNES_NORM_ALWAYS;
17596c67d002SPeter Brune   snes->functype             = SNES_FUNCTION_DEFAULT;
17608ca48ce9SPierre Jolivet   snes->rtol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
1761b4874afaSBarry Smith   snes->ttol                 = 0.0;
17628ca48ce9SPierre Jolivet   snes->abstol               = PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50;
17638ca48ce9SPierre Jolivet   snes->stol                 = PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8;
17648ca48ce9SPierre Jolivet   snes->deltatol             = PetscDefined(USE_REAL_SINGLE) ? 1.e-6 : 1.e-12;
1765e37c518bSBarry Smith   snes->divtol               = 1.e4;
1766e37c518bSBarry Smith   snes->rnorm0               = 0;
17679b94acceSBarry Smith   snes->nfuncs               = 0;
176850ffb88aSMatthew Knepley   snes->numFailures          = 0;
176950ffb88aSMatthew Knepley   snes->maxFailures          = 1;
17707a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1771e35cf81dSBarry Smith   snes->lagjacobian          = 1;
177237ec4e1aSPeter Brune   snes->jac_iter             = 0;
177337ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1774a8054027SBarry Smith   snes->lagpreconditioner    = 1;
177537ec4e1aSPeter Brune   snes->pre_iter             = 0;
177637ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1777639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1778c4421ceaSFande Kong   snes->numberreasonviews    = 0;
17799e5d0892SLisandro Dalcin   snes->data                 = NULL;
17804dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1781186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
17826f24a144SLois Curfman McInnes   snes->nwork                = 0;
17839e5d0892SLisandro Dalcin   snes->work                 = NULL;
178458c9b817SLisandro Dalcin   snes->nvwork               = 0;
17859e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1786758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1787758f92a0SBarry Smith   snes->conv_hist_max        = 0;
17880298fd71SBarry Smith   snes->conv_hist            = NULL;
17890298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1790758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1791971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1792e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1793184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1794efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1795b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1796c40d0f55SPeter Brune 
1797d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1798d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1799d8f46077SPeter Brune   snes->mf_version  = 1;
1800d8f46077SPeter Brune 
18013d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18023d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18033d4c4710SBarry Smith 
1804349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
180576bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1806349187a7SBarry Smith 
18074fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18084fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
18094fc747eaSLawrence Mitchell 
18109b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
18114dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1812f5af7f23SKarl Rupp 
18139b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
18149b94acceSBarry Smith   kctx->version     = 2;
18150f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
18169b94acceSBarry Smith                              this was too large for some test cases */
181775567043SBarry Smith   kctx->rtol_last   = 0.0;
18180f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
18199b94acceSBarry Smith   kctx->gamma       = 1.0;
18200f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
182171f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
18220f0abf79SStefano Zampini   kctx->threshold   = 0.1;
182375567043SBarry Smith   kctx->lresid_last = 0.0;
182475567043SBarry Smith   kctx->norm_last   = 0.0;
18259b94acceSBarry Smith 
18260f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
18270f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
18280f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
18290f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
18300f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
18310f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
18320f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
18330f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
18340f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
18350f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
18360f0abf79SStefano Zampini 
18379b94acceSBarry Smith   *outsnes = snes;
18383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18399b94acceSBarry Smith }
18409b94acceSBarry Smith 
18419b94acceSBarry Smith /*@C
18429b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1843f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
18449b94acceSBarry Smith   equations.
18459b94acceSBarry Smith 
1846c3339decSBarry Smith   Logically Collective
1847fee21e36SBarry Smith 
1848c7afd0dbSLois Curfman McInnes   Input Parameters:
1849f6dfbefdSBarry Smith + snes - the `SNES` context
1850dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
18518434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1852c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1853dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
18549b94acceSBarry Smith 
185536851e7fSLois Curfman McInnes   Level: beginner
185636851e7fSLois Curfman McInnes 
18578434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
18589b94acceSBarry Smith @*/
18598434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1860d71ae5a4SJacob Faibussowitsch {
18616cab3a1bSJed Brown   DM dm;
18626cab3a1bSJed Brown 
18633a40ed3dSBarry Smith   PetscFunctionBegin;
18640700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1865d2a683ecSLisandro Dalcin   if (r) {
1866d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1867d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
18689566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
18699566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
187085385478SLisandro Dalcin     snes->vec_func = r;
1871d2a683ecSLisandro Dalcin   }
18729566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
18739566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
187448a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
18753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18769b94acceSBarry Smith }
18779b94acceSBarry Smith 
1878e4ed7901SPeter Brune /*@C
18790b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1880e4ed7901SPeter Brune 
1881c3339decSBarry Smith   Logically Collective
1882e4ed7901SPeter Brune 
1883e4ed7901SPeter Brune   Input Parameters:
1884f6dfbefdSBarry Smith + snes - the `SNES` context
1885e4ed7901SPeter Brune - f    - vector to store function value
1886e4ed7901SPeter Brune 
1887dc4c0fb0SBarry Smith   Level: developer
1888dc4c0fb0SBarry Smith 
1889e4ed7901SPeter Brune   Notes:
1890e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1891e4ed7901SPeter Brune 
1892f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1893e4ed7901SPeter Brune 
18941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1895e4ed7901SPeter Brune @*/
1896d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1897d71ae5a4SJacob Faibussowitsch {
1898e4ed7901SPeter Brune   Vec vec_func;
1899e4ed7901SPeter Brune 
1900e4ed7901SPeter Brune   PetscFunctionBegin;
1901e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1902e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1903e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1904efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1905902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19063ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1907902f982fSPeter Brune   }
19089566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
19099566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
1910f5af7f23SKarl Rupp 
1911217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
19123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1913e4ed7901SPeter Brune }
1914e4ed7901SPeter Brune 
1915534ebe21SPeter Brune /*@
1916f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
1917f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
1918534ebe21SPeter Brune 
1919c3339decSBarry Smith   Logically Collective
1920534ebe21SPeter Brune 
1921534ebe21SPeter Brune   Input Parameters:
1922f6dfbefdSBarry Smith + snes         - the `SNES` context
1923365a6726SPeter Brune - normschedule - the frequency of norm computation
1924534ebe21SPeter Brune 
1925517f1916SMatthew G. Knepley   Options Database Key:
192667b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
1927517f1916SMatthew G. Knepley 
1928dc4c0fb0SBarry Smith   Level: advanced
1929dc4c0fb0SBarry Smith 
1930534ebe21SPeter Brune   Notes:
1931f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
1932534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
1933534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
1934f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
1935534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
1936534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
1937534ebe21SPeter Brune   their solution.
1938534ebe21SPeter Brune 
1939e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
1940534ebe21SPeter Brune @*/
1941d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
1942d71ae5a4SJacob Faibussowitsch {
1943534ebe21SPeter Brune   PetscFunctionBegin;
1944534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1945365a6726SPeter Brune   snes->normschedule = normschedule;
19463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1947534ebe21SPeter Brune }
1948534ebe21SPeter Brune 
1949534ebe21SPeter Brune /*@
1950f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
1951f6dfbefdSBarry Smith   of the `SNES` method.
1952534ebe21SPeter Brune 
1953c3339decSBarry Smith   Logically Collective
1954534ebe21SPeter Brune 
1955534ebe21SPeter Brune   Input Parameters:
1956f6dfbefdSBarry Smith + snes         - the `SNES` context
1957365a6726SPeter Brune - normschedule - the type of the norm used
1958534ebe21SPeter Brune 
1959534ebe21SPeter Brune   Level: advanced
1960534ebe21SPeter Brune 
19611cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1962534ebe21SPeter Brune @*/
1963d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
1964d71ae5a4SJacob Faibussowitsch {
1965534ebe21SPeter Brune   PetscFunctionBegin;
1966534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1967365a6726SPeter Brune   *normschedule = snes->normschedule;
19683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1969534ebe21SPeter Brune }
1970534ebe21SPeter Brune 
1971c5ce4427SMatthew G. Knepley /*@
1972c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
1973c5ce4427SMatthew G. Knepley 
1974c3339decSBarry Smith   Logically Collective
1975c5ce4427SMatthew G. Knepley 
1976c5ce4427SMatthew G. Knepley   Input Parameters:
1977f6dfbefdSBarry Smith + snes - the `SNES` context
1978f6dfbefdSBarry Smith - norm - the value of the norm
1979c5ce4427SMatthew G. Knepley 
1980c5ce4427SMatthew G. Knepley   Level: developer
1981c5ce4427SMatthew G. Knepley 
19821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
1983c5ce4427SMatthew G. Knepley @*/
1984d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
1985d71ae5a4SJacob Faibussowitsch {
1986c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
1987c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1988c5ce4427SMatthew G. Knepley   snes->norm = norm;
19893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1990c5ce4427SMatthew G. Knepley }
1991c5ce4427SMatthew G. Knepley 
1992c5ce4427SMatthew G. Knepley /*@
1993c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
1994c5ce4427SMatthew G. Knepley 
1995c5ce4427SMatthew G. Knepley   Not Collective
1996c5ce4427SMatthew G. Knepley 
1997c5ce4427SMatthew G. Knepley   Input Parameter:
1998f6dfbefdSBarry Smith . snes - the `SNES` context
1999c5ce4427SMatthew G. Knepley 
2000c5ce4427SMatthew G. Knepley   Output Parameter:
2001c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2002c5ce4427SMatthew G. Knepley 
2003c5ce4427SMatthew G. Knepley   Level: developer
2004c5ce4427SMatthew G. Knepley 
20051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2006c5ce4427SMatthew G. Knepley @*/
2007d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2008d71ae5a4SJacob Faibussowitsch {
2009c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2010c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20114f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2012c5ce4427SMatthew G. Knepley   *norm = snes->norm;
20133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2014c5ce4427SMatthew G. Knepley }
2015c5ce4427SMatthew G. Knepley 
2016c1e67a49SFande Kong /*@
2017f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2018c1e67a49SFande Kong 
2019c1e67a49SFande Kong   Not Collective
2020c1e67a49SFande Kong 
2021c1e67a49SFande Kong   Input Parameter:
2022f6dfbefdSBarry Smith . snes - the `SNES` context
2023c1e67a49SFande Kong 
2024c1e67a49SFande Kong   Output Parameter:
2025c1e67a49SFande Kong . ynorm - the last computed update norm
2026c1e67a49SFande Kong 
2027c1e67a49SFande Kong   Level: developer
2028c1e67a49SFande Kong 
2029f6dfbefdSBarry Smith   Note:
2030f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2031f6dfbefdSBarry Smith 
20321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2033c1e67a49SFande Kong @*/
2034d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2035d71ae5a4SJacob Faibussowitsch {
2036c1e67a49SFande Kong   PetscFunctionBegin;
2037c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20384f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2039c1e67a49SFande Kong   *ynorm = snes->ynorm;
20403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2041c1e67a49SFande Kong }
2042c1e67a49SFande Kong 
2043c1e67a49SFande Kong /*@
20444591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2045c1e67a49SFande Kong 
2046c1e67a49SFande Kong   Not Collective
2047c1e67a49SFande Kong 
2048c1e67a49SFande Kong   Input Parameter:
2049f6dfbefdSBarry Smith . snes - the `SNES` context
2050c1e67a49SFande Kong 
2051c1e67a49SFande Kong   Output Parameter:
2052c1e67a49SFande Kong . xnorm - the last computed solution norm
2053c1e67a49SFande Kong 
2054c1e67a49SFande Kong   Level: developer
2055c1e67a49SFande Kong 
20561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2057c1e67a49SFande Kong @*/
2058d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2059d71ae5a4SJacob Faibussowitsch {
2060c1e67a49SFande Kong   PetscFunctionBegin;
2061c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
20624f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2063c1e67a49SFande Kong   *xnorm = snes->xnorm;
20643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2065c1e67a49SFande Kong }
2066c1e67a49SFande Kong 
2067cc4c1da9SBarry Smith /*@
2068f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2069f6dfbefdSBarry Smith   of the `SNES` method.
207047073ea2SPeter Brune 
2071c3339decSBarry Smith   Logically Collective
207247073ea2SPeter Brune 
207347073ea2SPeter Brune   Input Parameters:
2074f6dfbefdSBarry Smith + snes - the `SNES` context
2075f6dfbefdSBarry Smith - type - the function type
207647073ea2SPeter Brune 
207747073ea2SPeter Brune   Level: developer
207847073ea2SPeter Brune 
2079420bcc1bSBarry Smith   Values of the function type\:
2080f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2081f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2082f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2083f6dfbefdSBarry Smith 
2084420bcc1bSBarry Smith   Note:
2085f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2086f6dfbefdSBarry Smith 
20871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
208847073ea2SPeter Brune @*/
2089d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2090d71ae5a4SJacob Faibussowitsch {
209147073ea2SPeter Brune   PetscFunctionBegin;
209247073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
209347073ea2SPeter Brune   snes->functype = type;
20943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209547073ea2SPeter Brune }
209647073ea2SPeter Brune 
2097cc4c1da9SBarry Smith /*@
2098f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
209947073ea2SPeter Brune   of the SNES method.
210047073ea2SPeter Brune 
2101c3339decSBarry Smith   Logically Collective
210247073ea2SPeter Brune 
210347073ea2SPeter Brune   Input Parameters:
2104f6dfbefdSBarry Smith + snes - the `SNES` context
2105f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
210647073ea2SPeter Brune 
210747073ea2SPeter Brune   Level: advanced
210847073ea2SPeter Brune 
21091cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
211047073ea2SPeter Brune @*/
2111d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2112d71ae5a4SJacob Faibussowitsch {
211347073ea2SPeter Brune   PetscFunctionBegin;
211447073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
211547073ea2SPeter Brune   *type = snes->functype;
21163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2117534ebe21SPeter Brune }
2118534ebe21SPeter Brune 
2119c79ef259SPeter Brune /*@C
2120be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2121c79ef259SPeter Brune   use with composed nonlinear solvers.
2122c79ef259SPeter Brune 
2123c79ef259SPeter Brune   Input Parameters:
21249bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
21258434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
2126c79ef259SPeter Brune - ctx  - [optional] user-defined context for private data for the
2127dc4c0fb0SBarry Smith             smoother evaluation routine (may be `NULL`)
2128c79ef259SPeter Brune 
2129dc4c0fb0SBarry Smith   Level: intermediate
2130dc4c0fb0SBarry Smith 
2131f6dfbefdSBarry Smith   Note:
2132f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2133f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2134c79ef259SPeter Brune 
21358434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2136c79ef259SPeter Brune @*/
21378434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2138d71ae5a4SJacob Faibussowitsch {
21396cab3a1bSJed Brown   DM dm;
21406cab3a1bSJed Brown 
2141646217ecSPeter Brune   PetscFunctionBegin;
21426cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21439566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21449566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
21453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2146646217ecSPeter Brune }
2147646217ecSPeter Brune 
2148bbc1464cSBarry Smith /*
2149bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2150bbc1464cSBarry Smith    changed during the KSPSolve()
2151bbc1464cSBarry Smith */
2152d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2153d71ae5a4SJacob Faibussowitsch {
2154bbc1464cSBarry Smith   DM     dm;
2155bbc1464cSBarry Smith   DMSNES sdm;
2156bbc1464cSBarry Smith 
2157bbc1464cSBarry Smith   PetscFunctionBegin;
21589566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21599566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2160bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2161bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2162792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
21639566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
21640df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2165ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2166792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21679566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2168bbc1464cSBarry Smith   } else {
2169792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
21709566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2171bbc1464cSBarry Smith   }
21723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2173bbc1464cSBarry Smith }
2174bbc1464cSBarry Smith 
2175d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2176d71ae5a4SJacob Faibussowitsch {
2177e03ab78fSPeter Brune   DM     dm;
2178942e3340SBarry Smith   DMSNES sdm;
21796cab3a1bSJed Brown 
21808b0a5094SBarry Smith   PetscFunctionBegin;
21819566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
21829566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
21838b0a5094SBarry 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));
2187792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
21889566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2189bbc1464cSBarry Smith   } else {
2190792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
21919566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2192bbc1464cSBarry Smith   }
21933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21948b0a5094SBarry Smith }
21958b0a5094SBarry Smith 
2196d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2197d71ae5a4SJacob Faibussowitsch {
21988b0a5094SBarry Smith   PetscFunctionBegin;
2199e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2200bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22019566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22048b0a5094SBarry Smith }
22058b0a5094SBarry Smith 
22068b0a5094SBarry Smith /*@C
22071d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22088b0a5094SBarry Smith 
2209c3339decSBarry Smith   Logically Collective
22108b0a5094SBarry Smith 
22118b0a5094SBarry Smith   Input Parameters:
2212f6dfbefdSBarry Smith + snes - the `SNES` context
2213dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
22148434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
22156b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2216dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
22178434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2218dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2219dc4c0fb0SBarry Smith 
2220dc4c0fb0SBarry Smith   Level: intermediate
22218b0a5094SBarry Smith 
22228b0a5094SBarry Smith   Notes:
22236b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2224f450aa47SBarry 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.
2225f450aa47SBarry Smith 
2226f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
22278b0a5094SBarry Smith 
22281d27aa22SBarry 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}$.
22291d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
22308b0a5094SBarry Smith 
2231dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
22328b0a5094SBarry Smith 
22330d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
22341d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
22358b0a5094SBarry Smith 
22368b0a5094SBarry 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
22371d27aa22SBarry 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
22381d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
22398b0a5094SBarry Smith 
22401d27aa22SBarry 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
2241f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
22426b7fb656SBarry Smith 
224315229ffcSPierre Jolivet   When used with `-snes_fd` this will compute the true Jacobian (very slowly one column at a time) and thus represent Newton's method.
22446b7fb656SBarry Smith 
2245dc4c0fb0SBarry 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
22466b7fb656SBarry 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
2247f6dfbefdSBarry 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`.
2248aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2249bbc1464cSBarry Smith 
22509bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
22518434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
22528b0a5094SBarry Smith @*/
22538434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2254d71ae5a4SJacob Faibussowitsch {
2255e03ab78fSPeter Brune   DM dm;
2256e03ab78fSPeter Brune 
22578b0a5094SBarry Smith   PetscFunctionBegin;
22588b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22609566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
22619566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
22629566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
22639566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
22643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22658b0a5094SBarry Smith }
22668b0a5094SBarry Smith 
22677971a8bfSPeter Brune /*@C
22687971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
22697971a8bfSPeter Brune 
2270f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
22717971a8bfSPeter Brune 
22727971a8bfSPeter Brune   Input Parameter:
2273f6dfbefdSBarry Smith . snes - the `SNES` context
22747971a8bfSPeter Brune 
2275d8d19677SJose E. Roman   Output Parameters:
2276dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
22778434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2278dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2279dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
22808434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2281dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
22827971a8bfSPeter Brune 
22837971a8bfSPeter Brune   Level: advanced
22847971a8bfSPeter Brune 
22858434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
22867971a8bfSPeter Brune @*/
22878434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2288d71ae5a4SJacob Faibussowitsch {
22897971a8bfSPeter Brune   DM dm;
22907971a8bfSPeter Brune 
22917971a8bfSPeter Brune   PetscFunctionBegin;
22927971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22939566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
22949566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
22959566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22969566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
22973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22987971a8bfSPeter Brune }
22997971a8bfSPeter Brune 
2300d25893d9SBarry Smith /*@C
2301dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2302d25893d9SBarry Smith 
2303c3339decSBarry Smith   Logically Collective
2304d25893d9SBarry Smith 
2305d25893d9SBarry Smith   Input Parameters:
2306f6dfbefdSBarry Smith + snes - the `SNES` context
23078434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2308d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2309dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2310d25893d9SBarry Smith 
2311d25893d9SBarry Smith   Level: intermediate
2312d25893d9SBarry Smith 
23138434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2314d25893d9SBarry Smith @*/
23158434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2316d71ae5a4SJacob Faibussowitsch {
2317d25893d9SBarry Smith   PetscFunctionBegin;
2318d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2319d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2320d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
23213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2322d25893d9SBarry Smith }
2323d25893d9SBarry Smith 
23241096aae1SMatthew Knepley /*@C
2325dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2326dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
23271096aae1SMatthew Knepley 
2328c3339decSBarry Smith   Logically Collective
23291096aae1SMatthew Knepley 
23301096aae1SMatthew Knepley   Input Parameter:
2331f6dfbefdSBarry Smith . snes - the `SNES` context
23321096aae1SMatthew Knepley 
23331096aae1SMatthew Knepley   Output Parameter:
2334dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
23351096aae1SMatthew Knepley 
23361096aae1SMatthew Knepley   Level: intermediate
23371096aae1SMatthew Knepley 
23381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
23391096aae1SMatthew Knepley @*/
2340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2341d71ae5a4SJacob Faibussowitsch {
23421096aae1SMatthew Knepley   PetscFunctionBegin;
23430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23444f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
234585385478SLisandro Dalcin   *rhs = snes->vec_rhs;
23463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23471096aae1SMatthew Knepley }
23481096aae1SMatthew Knepley 
23499b94acceSBarry Smith /*@
2350f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
23519b94acceSBarry Smith 
2352c3339decSBarry Smith   Collective
2353c7afd0dbSLois Curfman McInnes 
23549b94acceSBarry Smith   Input Parameters:
2355f6dfbefdSBarry Smith + snes - the `SNES` context
2356c7afd0dbSLois Curfman McInnes - x    - input vector
23579b94acceSBarry Smith 
23589b94acceSBarry Smith   Output Parameter:
2359f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
23609b94acceSBarry Smith 
2361dc4c0fb0SBarry Smith   Level: developer
2362dc4c0fb0SBarry Smith 
236300677de2SStefano Zampini   Notes:
2364f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2365bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
236636851e7fSLois Curfman McInnes 
236700677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
236800677de2SStefano Zampini 
23691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
23709b94acceSBarry Smith @*/
2371d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2372d71ae5a4SJacob Faibussowitsch {
23736cab3a1bSJed Brown   DM     dm;
2374942e3340SBarry Smith   DMSNES sdm;
23759b94acceSBarry Smith 
23763a40ed3dSBarry Smith   PetscFunctionBegin;
23770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23780700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
23790700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2380c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2381c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2382e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2383184914b5SBarry Smith 
23849566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23859566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
23860fdf79fbSJacob 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().");
238732f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
238848a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
23899566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
23908ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
23918ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2392800f99ffSJeremy L Thompson     {
2393800f99ffSJeremy L Thompson       void           *ctx;
23948434afd1SBarry Smith       SNESFunctionFn *computefunction;
2395800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2396800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2397800f99ffSJeremy L Thompson     }
23989566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
239948a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24000fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24019566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24020fdf79fbSJacob Faibussowitsch   }
24031baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2404ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2405422a814eSBarry Smith   /*
2406422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2407422a814eSBarry Smith      propagate the value to all processes
2408422a814eSBarry Smith   */
24091baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24119b94acceSBarry Smith }
24129b94acceSBarry Smith 
2413c79ef259SPeter Brune /*@
2414f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2415bbc1464cSBarry Smith 
2416c3339decSBarry Smith   Collective
2417bbc1464cSBarry Smith 
2418bbc1464cSBarry Smith   Input Parameters:
2419f6dfbefdSBarry Smith + snes - the `SNES` context
2420bbc1464cSBarry Smith - x    - input vector
2421bbc1464cSBarry Smith 
2422bbc1464cSBarry Smith   Output Parameter:
2423f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2424bbc1464cSBarry Smith 
2425dc4c0fb0SBarry Smith   Level: developer
2426dc4c0fb0SBarry Smith 
2427bbc1464cSBarry Smith   Notes:
2428420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2429bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2430bbc1464cSBarry Smith 
2431dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2432f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2433dd8e379bSPierre Jolivet   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.
2434bbc1464cSBarry Smith 
24351cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2436bbc1464cSBarry Smith @*/
2437d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2438d71ae5a4SJacob Faibussowitsch {
2439bbc1464cSBarry Smith   DM     dm;
2440bbc1464cSBarry Smith   DMSNES sdm;
2441bbc1464cSBarry Smith 
2442bbc1464cSBarry Smith   PetscFunctionBegin;
2443bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2444bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2445bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2446bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2447bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2448e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2449bbc1464cSBarry Smith 
24509566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24519566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24539566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2454bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2455bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2456792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
24579566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
24589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2459bbc1464cSBarry Smith   snes->nfuncs++;
2460bbc1464cSBarry Smith   /*
2461bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2462bbc1464cSBarry Smith      propagate the value to all processes
2463bbc1464cSBarry Smith   */
24641baa6e33SBarry Smith   if (snes->domainerror) PetscCall(VecSetInf(y));
24653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2466bbc1464cSBarry Smith }
2467bbc1464cSBarry Smith 
2468bbc1464cSBarry Smith /*@
2469f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2470c79ef259SPeter Brune 
2471c3339decSBarry Smith   Collective
2472c79ef259SPeter Brune 
2473c79ef259SPeter Brune   Input Parameters:
2474f6dfbefdSBarry Smith + snes - the `SNES` context
2475c79ef259SPeter Brune . x    - input vector
2476c79ef259SPeter Brune - b    - rhs vector
2477c79ef259SPeter Brune 
2478c79ef259SPeter Brune   Output Parameter:
2479c79ef259SPeter Brune . x - new solution vector
2480c79ef259SPeter Brune 
2481dc4c0fb0SBarry Smith   Level: developer
2482dc4c0fb0SBarry Smith 
2483f6dfbefdSBarry Smith   Note:
2484f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2485c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2486c79ef259SPeter Brune   themselves.
2487c79ef259SPeter Brune 
24888434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2489c79ef259SPeter Brune @*/
2490d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2491d71ae5a4SJacob Faibussowitsch {
24926cab3a1bSJed Brown   DM     dm;
2493942e3340SBarry Smith   DMSNES sdm;
2494646217ecSPeter Brune 
2495646217ecSPeter Brune   PetscFunctionBegin;
2496646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2497064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2498064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2499064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2500064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2501e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25039566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25049566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25050fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25069566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2507792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25089566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
25103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2511646217ecSPeter Brune }
2512646217ecSPeter Brune 
2513494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2514494a190aSStefano Zampini {
2515494a190aSStefano Zampini   Vec          X;
2516494a190aSStefano Zampini   PetscScalar *g;
2517494a190aSStefano Zampini   PetscReal    f, f2;
2518494a190aSStefano Zampini   PetscInt     low, high, N, i;
2519494a190aSStefano Zampini   PetscBool    flg;
2520494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2521494a190aSStefano Zampini 
2522494a190aSStefano Zampini   PetscFunctionBegin;
2523494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2524494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2525494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2526494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2527494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2528494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2529494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2530494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2531494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2532494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2533494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2534494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2535494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2536494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2537494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2538494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2539494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2540494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2541494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2542494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2543494a190aSStefano Zampini   }
2544494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2545494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2546494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2547494a190aSStefano Zampini }
2548494a190aSStefano Zampini 
2549494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2550494a190aSStefano Zampini {
2551494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2552494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2553494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2554494a190aSStefano Zampini   PetscScalar       dot;
2555494a190aSStefano Zampini   MPI_Comm          comm;
2556494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2557494a190aSStefano Zampini   PetscViewerFormat format;
2558494a190aSStefano Zampini   PetscInt          tabs;
2559494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
25608434afd1SBarry Smith   SNESObjectiveFn  *objective;
2561494a190aSStefano Zampini 
2562494a190aSStefano Zampini   PetscFunctionBegin;
2563494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2564494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2565494a190aSStefano Zampini 
2566494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2567494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2568494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2569494a190aSStefano Zampini   PetscOptionsEnd();
2570494a190aSStefano Zampini   if (!test) {
2571494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2572494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2573494a190aSStefano Zampini   }
2574494a190aSStefano Zampini 
2575494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2576494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2577494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2578494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2579494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2580494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2581494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2582494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2583494a190aSStefano Zampini   }
2584494a190aSStefano Zampini   if (!directionsprinted) {
2585494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2586494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2587494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2588494a190aSStefano Zampini   }
2589494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2590494a190aSStefano Zampini 
2591494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2592494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2593494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2594494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2595494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2596494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2597494a190aSStefano Zampini 
2598494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2599494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2600494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2601494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2602494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2603494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2604494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2605494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2606494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2607494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ||Ffd|| %g, ||F|| = %g, angle cosine = (Ffd'F)/||Ffd||||F|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot) / (fdnorm * hcnorm))));
2608494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2609494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2610494a190aSStefano Zampini 
2611494a190aSStefano Zampini   if (complete_print) {
2612494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2613494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2614494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2615494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2616494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2617494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2618494a190aSStefano Zampini   }
2619494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2620494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2621494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2622494a190aSStefano Zampini 
2623494a190aSStefano Zampini   if (complete_print) {
2624494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2625494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2626494a190aSStefano Zampini   }
2627494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2628494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2629494a190aSStefano Zampini }
2630494a190aSStefano Zampini 
2631d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2632d71ae5a4SJacob Faibussowitsch {
263312837594SBarry Smith   Mat               A, B, C, D, jacobian;
26344df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2635e885f1abSBarry Smith   PetscReal         nrm, gnorm;
263681e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
26370e276705SLisandro Dalcin   MatType           mattype;
2638e885f1abSBarry Smith   PetscInt          m, n, M, N;
2639e885f1abSBarry Smith   void             *functx;
26402cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
26413325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2642e885f1abSBarry Smith   MPI_Comm          comm;
2643e885f1abSBarry Smith   PetscInt          tabs;
264412837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
26453325ff46SBarry Smith   PetscViewerFormat format;
2646e885f1abSBarry Smith 
2647e885f1abSBarry Smith   PetscFunctionBegin;
2648d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
26499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
26509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
26519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
26524ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
26539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
26549566063dSJacob 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));
2655d0609cedSBarry Smith   PetscOptionsEnd();
26563ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2657e885f1abSBarry Smith 
26589566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
26599566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
26609566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
26619566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
26629566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
266312837594SBarry Smith   if (!complete_print && !directionsprinted) {
26649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
26659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
266612837594SBarry Smith   }
266712837594SBarry Smith   if (!directionsprinted) {
26689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
26699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
267012837594SBarry Smith     directionsprinted = PETSC_TRUE;
2671e885f1abSBarry Smith   }
26721baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2673e885f1abSBarry Smith 
26749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
267512837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
267612837594SBarry Smith   else jacobian = snes->jacobian_pre;
267712837594SBarry Smith 
26784df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
26794df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
26809566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
26814df93895SStefano Zampini 
2682a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
26839566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
26849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
26859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
268612837594SBarry Smith   while (jacobian) {
26872cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
26882cd624f9SStefano Zampini 
26892cd624f9SStefano Zampini     if (istranspose) {
26909566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
26912cd624f9SStefano Zampini       Jsave    = jacobian;
26922cd624f9SStefano Zampini       jacobian = JT;
26932cd624f9SStefano Zampini     }
26949566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
269512837594SBarry Smith     if (flg) {
269612837594SBarry Smith       A = jacobian;
26979566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
269812837594SBarry Smith     } else {
26999566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
270012837594SBarry Smith     }
2701e885f1abSBarry Smith 
27029566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
27039566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
27049566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
27059566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
27069566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
27079566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
27089566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
27099566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
27109566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2711e885f1abSBarry Smith 
27129566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
27139566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
271412837594SBarry Smith 
27159566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
27169566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
27179566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
27189566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
27199566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
272012837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
27219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
272212837594SBarry Smith 
2723e885f1abSBarry Smith     if (complete_print) {
27249566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
27259566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
27269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
27279566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2728e885f1abSBarry Smith     }
2729e885f1abSBarry Smith 
2730df10fb39SFande Kong     if (threshold_print || complete_print) {
2731e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2732e885f1abSBarry Smith       PetscScalar       *cvals;
2733e885f1abSBarry Smith       const PetscInt    *bcols;
2734e885f1abSBarry Smith       const PetscScalar *bvals;
2735e885f1abSBarry Smith 
27369566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
27379566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
27389566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
27399566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
27409566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
27419566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
27420e276705SLisandro Dalcin 
27439566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
27449566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2745e885f1abSBarry Smith 
2746e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
27479566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
27489566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2749e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
275023a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2751e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2752e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2753e885f1abSBarry Smith             cncols += 1;
2754e885f1abSBarry Smith           }
2755e885f1abSBarry Smith         }
275648a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
27579566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
27589566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2759e885f1abSBarry Smith       }
27609566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
27619566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
27629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
27639566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
27649566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2765e885f1abSBarry Smith     }
27669566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
27679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
27689566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
27692cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
277012837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
277112837594SBarry Smith       jacobian = snes->jacobian_pre;
27729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
27739371c9d4SSatish Balay     } else jacobian = NULL;
277412837594SBarry Smith   }
27759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
27761baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2777cd791dc2SBarry Smith   if (mviewer) PetscCall(PetscOptionsRestoreViewer(&mviewer));
27789566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
27793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2780e885f1abSBarry Smith }
2781e885f1abSBarry Smith 
278262fef451SLois Curfman McInnes /*@
2783f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
278462fef451SLois Curfman McInnes 
2785c3339decSBarry Smith   Collective
2786c7afd0dbSLois Curfman McInnes 
278762fef451SLois Curfman McInnes   Input Parameters:
2788f6dfbefdSBarry Smith + snes - the `SNES` context
2789e4094ef1SJacob Faibussowitsch - X    - input vector
279062fef451SLois Curfman McInnes 
279162fef451SLois Curfman McInnes   Output Parameters:
2792c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2793420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2794fee21e36SBarry Smith 
2795e35cf81dSBarry Smith   Options Database Keys:
279667b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
279767b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2798455a5933SJed 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.
2799455a5933SJed 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
2800693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2801693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2802693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
28034c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
280494d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2805a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2806c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2807dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2808dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2809a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2810a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2811c01495d3SJed Brown 
2812dc4c0fb0SBarry Smith   Level: developer
2813dc4c0fb0SBarry Smith 
2814f6dfbefdSBarry Smith   Note:
281562fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
281662fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
281762fef451SLois Curfman McInnes 
2818420bcc1bSBarry Smith   Developer Note:
2819dc4c0fb0SBarry 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
2820420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2821e885f1abSBarry Smith 
28221cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
282362fef451SLois Curfman McInnes @*/
2824d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2825d71ae5a4SJacob Faibussowitsch {
2826ace3abfcSBarry Smith   PetscBool flag;
28276cab3a1bSJed Brown   DM        dm;
2828942e3340SBarry Smith   DMSNES    sdm;
2829e0e3a89bSBarry Smith   KSP       ksp;
28303a40ed3dSBarry Smith 
28313a40ed3dSBarry Smith   PetscFunctionBegin;
28320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
28330700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2834c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2835e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
28369566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
28379566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
28383232da50SPeter Brune 
283901c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2840fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2841fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2842f5af7f23SKarl Rupp 
28439566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2844fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
28459566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
28469566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2847ebd3b9afSBarry Smith     if (flag) {
28489566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28499566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2850ebd3b9afSBarry Smith     }
28513ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
285237ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
285363a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
28549566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2855ebd3b9afSBarry Smith     if (flag) {
28569566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28579566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2858ebd3b9afSBarry Smith     }
28593ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2860e35cf81dSBarry Smith   }
2861efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
28629566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
28639566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
28643ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2865d728fb7dSPeter Brune   }
2866e35cf81dSBarry Smith 
28679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
28689566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2869800f99ffSJeremy L Thompson   {
2870800f99ffSJeremy L Thompson     void           *ctx;
28718434afd1SBarry Smith     SNESJacobianFn *J;
2872800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2873800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2874800f99ffSJeremy L Thompson   }
28759566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
28769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
287728d58a37SPierre Jolivet 
287828d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
28799566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2880a8054027SBarry Smith 
2881e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
28829566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
28833b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
28849566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
28859566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
28863b4f5425SBarry Smith     snes->lagpreconditioner = -1;
28873b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
28889566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
28899566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
289037ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
289163a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
28929566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2893d1e9a80fSBarry Smith   } else {
28949566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
28959566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2896a8054027SBarry Smith   }
2897a8054027SBarry Smith 
28984df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
28994df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
29004df93895SStefano Zampini   {
29014df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
29024df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
29034df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
29044df93895SStefano Zampini 
29054df93895SStefano Zampini     snes->vec_sol      = X;
29064df93895SStefano Zampini     snes->jacobian     = A;
29074df93895SStefano Zampini     snes->jacobian_pre = B;
2908494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
29099566063dSJacob Faibussowitsch     PetscCall(SNESTestJacobian(snes));
2910494a190aSStefano Zampini 
29114df93895SStefano Zampini     snes->vec_sol      = xsave;
29124df93895SStefano Zampini     snes->jacobian     = jacobiansave;
29134df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
29144df93895SStefano Zampini   }
29154df93895SStefano Zampini 
2916693365a8SJed Brown   {
2917693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
29189566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
29199566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
29209566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
29219566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
2922693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
29230298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
2924693365a8SJed Brown       PetscViewer vdraw, vstdout;
29256b3a5b13SJed Brown       PetscBool   flg;
2926693365a8SJed Brown       if (flag_operator) {
29279566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
2928693365a8SJed Brown         Bexp = Bexp_mine;
2929693365a8SJed Brown       } else {
2930693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
29319566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
293294ab13aaSBarry Smith         if (flg) Bexp = B;
2933693365a8SJed Brown         else {
2934693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
29359566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
2936693365a8SJed Brown           Bexp = Bexp_mine;
2937693365a8SJed Brown         }
2938693365a8SJed Brown       }
29399566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
29409566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
29419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
2942693365a8SJed Brown       if (flag_draw || flag_contour) {
29439566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
29449566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29450298fd71SBarry Smith       } else vdraw = NULL;
29469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
29479566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
29489566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
29499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
29509566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
29519566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
29529566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
29539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
29549566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
2955693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
29569566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
29579566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
29589566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
2959693365a8SJed Brown       }
29609566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
29619566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
29629566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
29639566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
2964693365a8SJed Brown     }
2965693365a8SJed Brown   }
29664c30e9fbSJed Brown   {
29676719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
29686719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
29699566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
29709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
29719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
29729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
29739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
297427b0f280SBarry Smith     if (flag_threshold) {
29759566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
29769566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
297727b0f280SBarry Smith     }
29786719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
29794c30e9fbSJed Brown       Mat             Bfd;
29804c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
2981335efc43SPeter Brune       MatColoring     coloring;
29824c30e9fbSJed Brown       ISColoring      iscoloring;
29834c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
29848434afd1SBarry Smith       SNESFunctionFn *func;
29854c30e9fbSJed Brown       void           *funcctx;
29866719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
29874c30e9fbSJed Brown 
29889566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
29899566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
29909566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
29919566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
29929566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
29939566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
29949566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
29959566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
29969566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
29979566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
29984c30e9fbSJed Brown 
29994c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
30009566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
30019566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))func, funcctx));
30029566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
30039566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
30049566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30059566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
30069566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
30074c30e9fbSJed Brown 
30089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
30094c30e9fbSJed Brown       if (flag_draw || flag_contour) {
30109566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30119566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30120298fd71SBarry Smith       } else vdraw = NULL;
30139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
30149566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
30159566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
30169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
30179566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30189566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
30199566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
30209566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
30219566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
30229566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
30239566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
30249566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
30254c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
30269566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30279566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
30289566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
30294c30e9fbSJed Brown       }
30309566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30316719d8e4SJed Brown 
30326719d8e4SJed Brown       if (flag_threshold) {
30336719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
30349566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
30359566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
30366719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
30376719d8e4SJed Brown           const PetscScalar *ba, *ca;
30386719d8e4SJed Brown           const PetscInt    *bj, *cj;
30396719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
30406719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
30419566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
30429566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
30435f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
30446719d8e4SJed Brown           for (j = 0; j < bn; j++) {
30456719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
30466719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
30476719d8e4SJed Brown               maxentrycol = bj[j];
30486719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
30496719d8e4SJed Brown             }
30506719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
30516719d8e4SJed Brown               maxdiffcol = bj[j];
30526719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
30536719d8e4SJed Brown             }
30546719d8e4SJed Brown             if (rdiff > maxrdiff) {
30556719d8e4SJed Brown               maxrdiffcol = bj[j];
30566719d8e4SJed Brown               maxrdiff    = rdiff;
30576719d8e4SJed Brown             }
30586719d8e4SJed Brown           }
30596719d8e4SJed Brown           if (maxrdiff > 1) {
306063a3b9bcSJacob 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));
30616719d8e4SJed Brown             for (j = 0; j < bn; j++) {
30626719d8e4SJed Brown               PetscReal rdiff;
30636719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
306448a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
30656719d8e4SJed Brown             }
306663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
30676719d8e4SJed Brown           }
30689566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
30699566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
30706719d8e4SJed Brown         }
30716719d8e4SJed Brown       }
30729566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30739566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
30744c30e9fbSJed Brown     }
30754c30e9fbSJed Brown   }
30763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30779b94acceSBarry Smith }
30789b94acceSBarry Smith 
30799b94acceSBarry Smith /*@C
30809b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3081044dda88SLois Curfman McInnes   location to store the matrix.
30829b94acceSBarry Smith 
3083c3339decSBarry Smith   Logically Collective
3084c7afd0dbSLois Curfman McInnes 
30859b94acceSBarry Smith   Input Parameters:
3086f6dfbefdSBarry Smith + snes - the `SNES` context
3087e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3088dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
30898434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3090c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3091dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3092dc4c0fb0SBarry Smith 
3093dc4c0fb0SBarry Smith   Level: beginner
30949b94acceSBarry Smith 
30959b94acceSBarry Smith   Notes:
3096dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
309716913363SBarry Smith   each matrix.
309816913363SBarry Smith 
3099dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3100dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3101895c21f2SBarry Smith 
3102dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3103f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3104a8a26c1eSJed Brown 
3105c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3106f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3107c3cc8fd1SJed Brown 
31081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
31098434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
31109b94acceSBarry Smith @*/
31118434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3112d71ae5a4SJacob Faibussowitsch {
31136cab3a1bSJed Brown   DM dm;
31143a7fca6bSBarry Smith 
31153a40ed3dSBarry Smith   PetscFunctionBegin;
31160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3117e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3118e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3119e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3120e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
31219566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31229566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3123e5d3d808SBarry Smith   if (Amat) {
31249566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
31259566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3126f5af7f23SKarl Rupp 
3127e5d3d808SBarry Smith     snes->jacobian = Amat;
31283a7fca6bSBarry Smith   }
3129e5d3d808SBarry Smith   if (Pmat) {
31309566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
31319566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3132f5af7f23SKarl Rupp 
3133e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
31343a7fca6bSBarry Smith   }
31353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31369b94acceSBarry Smith }
313762fef451SLois Curfman McInnes 
3138c2aafc4cSSatish Balay /*@C
3139b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3140b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3141b4fd4287SBarry Smith 
3142420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3143c7afd0dbSLois Curfman McInnes 
3144b4fd4287SBarry Smith   Input Parameter:
3145b4fd4287SBarry Smith . snes - the nonlinear solver context
3146b4fd4287SBarry Smith 
3147b4fd4287SBarry Smith   Output Parameters:
3148dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3149dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
31508434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3151dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3152fee21e36SBarry Smith 
315336851e7fSLois Curfman McInnes   Level: advanced
315436851e7fSLois Curfman McInnes 
31558434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3156b4fd4287SBarry Smith @*/
31578434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3158d71ae5a4SJacob Faibussowitsch {
31596cab3a1bSJed Brown   DM dm;
31606cab3a1bSJed Brown 
31613a40ed3dSBarry Smith   PetscFunctionBegin;
31620700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3163e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3164e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
31659566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3166800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
31673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3168b4fd4287SBarry Smith }
3169b4fd4287SBarry Smith 
3170d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3171d71ae5a4SJacob Faibussowitsch {
317258b371f3SBarry Smith   DM     dm;
317358b371f3SBarry Smith   DMSNES sdm;
317458b371f3SBarry Smith 
317558b371f3SBarry Smith   PetscFunctionBegin;
31769566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
31779566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
317858b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
317958b371f3SBarry Smith     DM        dm;
318058b371f3SBarry Smith     PetscBool isdense, ismf;
318158b371f3SBarry Smith 
31829566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
31839566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
31849566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
318558b371f3SBarry Smith     if (isdense) {
31869566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
318758b371f3SBarry Smith     } else if (!ismf) {
31889566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
318958b371f3SBarry Smith     }
319058b371f3SBarry Smith   }
31913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
319258b371f3SBarry Smith }
319358b371f3SBarry Smith 
31949b94acceSBarry Smith /*@
31959b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3196272ac6f2SLois Curfman McInnes   of a nonlinear solver.
31979b94acceSBarry Smith 
3198c3339decSBarry Smith   Collective
3199fee21e36SBarry Smith 
32002fe279fdSBarry Smith   Input Parameter:
3201f6dfbefdSBarry Smith . snes - the `SNES` context
3202c7afd0dbSLois Curfman McInnes 
3203dc4c0fb0SBarry Smith   Level: advanced
3204dc4c0fb0SBarry Smith 
3205f6dfbefdSBarry Smith   Note:
3206f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3207f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3208f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3209f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3210f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3211272ac6f2SLois Curfman McInnes 
32121cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
32139b94acceSBarry Smith @*/
3214d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3215d71ae5a4SJacob Faibussowitsch {
32166cab3a1bSJed Brown   DM             dm;
3217942e3340SBarry Smith   DMSNES         sdm;
3218c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
32196e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
32209b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
32219b5c1c08SStefano Zampini   Vec            f, fpc;
32229b5c1c08SStefano Zampini   void          *funcctx;
32239b5c1c08SStefano Zampini   void          *jacctx, *appctx;
32249b5c1c08SStefano Zampini   Mat            j, jpre;
32256b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
32266b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
32278434afd1SBarry Smith   SNESFunctionFn *func;
32288434afd1SBarry Smith   SNESJacobianFn *jac;
32293a40ed3dSBarry Smith 
32303a40ed3dSBarry Smith   PetscFunctionBegin;
32310700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
32323ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3233fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
32349b94acceSBarry Smith 
323548a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
323685385478SLisandro Dalcin 
32379566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
323858c9b817SLisandro Dalcin 
32399566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32409566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
32419566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
324258b371f3SBarry Smith 
324348a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3244efd51863SBarry Smith 
324548a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3246b710008aSBarry Smith 
3247d8d34be6SBarry Smith   if (snes->linesearch) {
32489566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
32499566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3250d8d34be6SBarry Smith   }
32519e764e56SPeter Brune 
32529b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3253b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3254172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3255172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3256172a4300SPeter Brune   }
3257d8f46077SPeter Brune 
3258efd4aadfSBarry Smith   if (snes->npc) {
32596e2a1849SPeter Brune     /* copy the DM over */
32609566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32619566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
32626e2a1849SPeter Brune 
32639566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
32649566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
32659566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
32669566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
32679566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
32689566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
32699566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
32709b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
32719566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
32726e2a1849SPeter Brune 
32736e2a1849SPeter Brune     /* copy the function pointers over */
32749566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
32756e2a1849SPeter Brune 
32766e2a1849SPeter Brune     /* default to 1 iteration */
32779566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3278efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
32799566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3280a9936a0cSPeter Brune     } else {
32819566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3282a9936a0cSPeter Brune     }
32839566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
32846e2a1849SPeter Brune 
32856e2a1849SPeter Brune     /* copy the line search context over */
3286d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
32879566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
32889566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
32899566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
32909566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
32919566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
32929566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
32939566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
32946e2a1849SPeter Brune     }
3295d8d34be6SBarry Smith   }
32961baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
32979927e4dfSBarry Smith   if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user));
32986e2a1849SPeter Brune 
329937ec4e1aSPeter Brune   snes->jac_iter = 0;
330037ec4e1aSPeter Brune   snes->pre_iter = 0;
330137ec4e1aSPeter Brune 
3302dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
330358c9b817SLisandro Dalcin 
33049566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
330558b371f3SBarry Smith 
3306b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
33076c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3308d8d34be6SBarry Smith       if (snes->linesearch) {
33099566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
33109566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
33116c67d002SPeter Brune       }
33126c67d002SPeter Brune     }
3313d8d34be6SBarry Smith   }
3314fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
33157aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
33163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33179b94acceSBarry Smith }
33189b94acceSBarry Smith 
331937596af1SLisandro Dalcin /*@
3320f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
332137596af1SLisandro Dalcin 
3322c3339decSBarry Smith   Collective
332337596af1SLisandro Dalcin 
332437596af1SLisandro Dalcin   Input Parameter:
3325f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
332637596af1SLisandro Dalcin 
3327d25893d9SBarry Smith   Level: intermediate
3328d25893d9SBarry Smith 
332995452b02SPatrick Sanan   Notes:
3330f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
333137596af1SLisandro Dalcin 
3332f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3333f6dfbefdSBarry Smith 
33341cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
333537596af1SLisandro Dalcin @*/
3336d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3337d71ae5a4SJacob Faibussowitsch {
333837596af1SLisandro Dalcin   PetscFunctionBegin;
333937596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3340d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
33419927e4dfSBarry Smith     PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user));
33420298fd71SBarry Smith     snes->user = NULL;
3343d25893d9SBarry Smith   }
33441baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
33458a23116dSBarry Smith 
3346dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
33471baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
33489e764e56SPeter Brune 
33491baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
33509e764e56SPeter Brune 
33519566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
33529566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
33539566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
33549566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
33559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
33569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
33579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
33589566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
33599566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3360f5af7f23SKarl Rupp 
336140fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
336240fdac6aSLawrence Mitchell 
336337596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
336437596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
33653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
336637596af1SLisandro Dalcin }
336737596af1SLisandro Dalcin 
336852baeb72SSatish Balay /*@
3369420bcc1bSBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()`
3370c4421ceaSFande Kong 
3371c3339decSBarry Smith   Collective
3372c4421ceaSFande Kong 
3373c4421ceaSFande Kong   Input Parameter:
3374f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3375c4421ceaSFande Kong 
3376c4421ceaSFande Kong   Level: intermediate
3377c4421ceaSFande Kong 
3378420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3379c4421ceaSFande Kong @*/
3380d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3381d71ae5a4SJacob Faibussowitsch {
3382c4421ceaSFande Kong   PetscInt i;
3383c4421ceaSFande Kong 
3384c4421ceaSFande Kong   PetscFunctionBegin;
3385c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3386c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
338748a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3388c4421ceaSFande Kong   }
3389c4421ceaSFande Kong   snes->numberreasonviews = 0;
33903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3391c4421ceaSFande Kong }
3392c4421ceaSFande Kong 
33931fb7b255SJunchao Zhang /*@C
33949b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3395f6dfbefdSBarry Smith   with `SNESCreate()`.
33969b94acceSBarry Smith 
3397c3339decSBarry Smith   Collective
3398c7afd0dbSLois Curfman McInnes 
33999b94acceSBarry Smith   Input Parameter:
3400f6dfbefdSBarry Smith . snes - the `SNES` context
34019b94acceSBarry Smith 
340236851e7fSLois Curfman McInnes   Level: beginner
340336851e7fSLois Curfman McInnes 
34041cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
34059b94acceSBarry Smith @*/
3406d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3407d71ae5a4SJacob Faibussowitsch {
34083a40ed3dSBarry Smith   PetscFunctionBegin;
34093ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3410f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3411f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
34129371c9d4SSatish Balay     *snes = NULL;
34133ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
34149371c9d4SSatish Balay   }
3415d4bb536fSBarry Smith 
3416f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
34179566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
34186b8b9a38SLisandro Dalcin 
3419e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
34209566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3421f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
34226d4c513bSLisandro Dalcin 
34239566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
34249566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
34259566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
34269566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
34276b8b9a38SLisandro Dalcin 
34289566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
342948a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
343048a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3431f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3432f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
34339566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
34343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34359b94acceSBarry Smith }
34369b94acceSBarry Smith 
34379b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
34389b94acceSBarry Smith 
3439a8054027SBarry Smith /*@
3440a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3441a8054027SBarry Smith 
3442c3339decSBarry Smith   Logically Collective
3443a8054027SBarry Smith 
3444a8054027SBarry Smith   Input Parameters:
3445f6dfbefdSBarry Smith + snes - the `SNES` context
3446d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
34473b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3448a8054027SBarry Smith 
3449a8054027SBarry Smith   Options Database Keys:
3450420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
34513d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3452420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
34533d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3454a8054027SBarry Smith 
3455dc4c0fb0SBarry Smith   Level: intermediate
3456dc4c0fb0SBarry Smith 
3457420bcc1bSBarry Smith   Notes:
3458a8054027SBarry Smith   The default is 1
3459420bcc1bSBarry Smith 
3460f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3461d8e291bfSBarry Smith 
3462f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3463a8054027SBarry Smith 
34641cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3465f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3466a8054027SBarry Smith @*/
3467d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3468d71ae5a4SJacob Faibussowitsch {
3469a8054027SBarry Smith   PetscFunctionBegin;
34700700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34715f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
34725f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3473c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3474a8054027SBarry Smith   snes->lagpreconditioner = lag;
34753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3476a8054027SBarry Smith }
3477a8054027SBarry Smith 
3478efd51863SBarry Smith /*@
3479f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3480efd51863SBarry Smith 
3481c3339decSBarry Smith   Logically Collective
3482efd51863SBarry Smith 
3483efd51863SBarry Smith   Input Parameters:
3484f6dfbefdSBarry Smith + snes  - the `SNES` context
3485efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3486efd51863SBarry Smith 
3487f6dfbefdSBarry Smith   Options Database Key:
348867b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3489efd51863SBarry Smith 
3490efd51863SBarry Smith   Level: intermediate
3491efd51863SBarry Smith 
3492f6dfbefdSBarry Smith   Note:
3493f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3494c0df2a02SJed Brown 
3495420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
3496420bcc1bSBarry Smith           `SNESetDM()`
3497efd51863SBarry Smith @*/
3498d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3499d71ae5a4SJacob Faibussowitsch {
3500efd51863SBarry Smith   PetscFunctionBegin;
3501efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3502efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3503efd51863SBarry Smith   snes->gridsequence = steps;
35043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3505efd51863SBarry Smith }
3506efd51863SBarry Smith 
3507fa19ca70SBarry Smith /*@
3508f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3509fa19ca70SBarry Smith 
3510c3339decSBarry Smith   Logically Collective
3511fa19ca70SBarry Smith 
3512fa19ca70SBarry Smith   Input Parameter:
3513f6dfbefdSBarry Smith . snes - the `SNES` context
3514fa19ca70SBarry Smith 
3515fa19ca70SBarry Smith   Output Parameter:
3516fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3517fa19ca70SBarry Smith 
3518fa19ca70SBarry Smith   Level: intermediate
3519fa19ca70SBarry Smith 
35201cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3521fa19ca70SBarry Smith @*/
3522d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3523d71ae5a4SJacob Faibussowitsch {
3524fa19ca70SBarry Smith   PetscFunctionBegin;
3525fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3526fa19ca70SBarry Smith   *steps = snes->gridsequence;
35273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3528fa19ca70SBarry Smith }
3529fa19ca70SBarry Smith 
3530a8054027SBarry Smith /*@
3531f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3532a8054027SBarry Smith 
35333f9fe445SBarry Smith   Not Collective
3534a8054027SBarry Smith 
3535a8054027SBarry Smith   Input Parameter:
3536f6dfbefdSBarry Smith . snes - the `SNES` context
3537a8054027SBarry Smith 
3538a8054027SBarry Smith   Output Parameter:
3539a8054027SBarry 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
35403b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3541a8054027SBarry Smith 
3542dc4c0fb0SBarry Smith   Level: intermediate
3543dc4c0fb0SBarry Smith 
3544a8054027SBarry Smith   Notes:
3545a8054027SBarry Smith   The default is 1
3546f6dfbefdSBarry Smith 
3547a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3548a8054027SBarry Smith 
35491cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3550a8054027SBarry Smith @*/
3551d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3552d71ae5a4SJacob Faibussowitsch {
3553a8054027SBarry Smith   PetscFunctionBegin;
35540700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3555a8054027SBarry Smith   *lag = snes->lagpreconditioner;
35563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3557a8054027SBarry Smith }
3558a8054027SBarry Smith 
3559e35cf81dSBarry Smith /*@
3560f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3561e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3562e35cf81dSBarry Smith 
3563c3339decSBarry Smith   Logically Collective
3564e35cf81dSBarry Smith 
3565e35cf81dSBarry Smith   Input Parameters:
3566f6dfbefdSBarry Smith + snes - the `SNES` context
3567e35cf81dSBarry 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
3568fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3569e35cf81dSBarry Smith 
3570e35cf81dSBarry Smith   Options Database Keys:
357179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
35723d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
357379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
35743d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3575e35cf81dSBarry Smith 
3576dc4c0fb0SBarry Smith   Level: intermediate
3577dc4c0fb0SBarry Smith 
3578e35cf81dSBarry Smith   Notes:
3579e35cf81dSBarry Smith   The default is 1
3580f6dfbefdSBarry Smith 
3581e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3582f6dfbefdSBarry Smith 
3583fe3ffe1eSBarry 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
3584fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3585e35cf81dSBarry Smith 
35861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3587e35cf81dSBarry Smith @*/
3588d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3589d71ae5a4SJacob Faibussowitsch {
3590e35cf81dSBarry Smith   PetscFunctionBegin;
35910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35925f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35935f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3594c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3595e35cf81dSBarry Smith   snes->lagjacobian = lag;
35963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3597e35cf81dSBarry Smith }
3598e35cf81dSBarry Smith 
3599e35cf81dSBarry Smith /*@
3600f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3601e35cf81dSBarry Smith 
36023f9fe445SBarry Smith   Not Collective
3603e35cf81dSBarry Smith 
3604e35cf81dSBarry Smith   Input Parameter:
3605f6dfbefdSBarry Smith . snes - the `SNES` context
3606e35cf81dSBarry Smith 
3607e35cf81dSBarry Smith   Output Parameter:
3608e35cf81dSBarry 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
3609e35cf81dSBarry Smith          the Jacobian is built etc.
3610e35cf81dSBarry Smith 
3611dc4c0fb0SBarry Smith   Level: intermediate
3612dc4c0fb0SBarry Smith 
3613e35cf81dSBarry Smith   Notes:
3614e35cf81dSBarry Smith   The default is 1
3615f6dfbefdSBarry Smith 
3616f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3617e35cf81dSBarry Smith 
36181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3619e35cf81dSBarry Smith 
3620e35cf81dSBarry Smith @*/
3621d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3622d71ae5a4SJacob Faibussowitsch {
3623e35cf81dSBarry Smith   PetscFunctionBegin;
36240700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3625e35cf81dSBarry Smith   *lag = snes->lagjacobian;
36263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3627e35cf81dSBarry Smith }
3628e35cf81dSBarry Smith 
362937ec4e1aSPeter Brune /*@
3630f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
363137ec4e1aSPeter Brune 
3632c3339decSBarry Smith   Logically collective
363337ec4e1aSPeter Brune 
3634d8d19677SJose E. Roman   Input Parameters:
3635f6dfbefdSBarry Smith + snes - the `SNES` context
36369d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
363737ec4e1aSPeter Brune 
363837ec4e1aSPeter Brune   Options Database Keys:
363979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36403d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
364179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36423d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
36433d5a8a6aSBarry Smith 
3644dc4c0fb0SBarry Smith   Level: advanced
3645dc4c0fb0SBarry Smith 
364695452b02SPatrick Sanan   Notes:
3647420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3648f6dfbefdSBarry Smith 
364995452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
365037ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
365137ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
365237ec4e1aSPeter Brune 
365342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
365437ec4e1aSPeter Brune @*/
3655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3656d71ae5a4SJacob Faibussowitsch {
365737ec4e1aSPeter Brune   PetscFunctionBegin;
365837ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
365937ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
366037ec4e1aSPeter Brune   snes->lagjac_persist = flg;
36613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
366237ec4e1aSPeter Brune }
366337ec4e1aSPeter Brune 
366437ec4e1aSPeter Brune /*@
3665d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
366637ec4e1aSPeter Brune 
3667c3339decSBarry Smith   Logically Collective
366837ec4e1aSPeter Brune 
3669d8d19677SJose E. Roman   Input Parameters:
3670f6dfbefdSBarry Smith + snes - the `SNES` context
36719d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
367237ec4e1aSPeter Brune 
367337ec4e1aSPeter Brune   Options Database Keys:
367479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36753d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
367679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36773d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
367837ec4e1aSPeter Brune 
3679dc4c0fb0SBarry Smith   Level: developer
3680dc4c0fb0SBarry Smith 
368195452b02SPatrick Sanan   Notes:
3682420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3683f6dfbefdSBarry Smith 
368495452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
368537ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
368637ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
368737ec4e1aSPeter Brune 
36881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
368937ec4e1aSPeter Brune @*/
3690d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3691d71ae5a4SJacob Faibussowitsch {
369237ec4e1aSPeter Brune   PetscFunctionBegin;
369337ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
369437ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
369537ec4e1aSPeter Brune   snes->lagpre_persist = flg;
36963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
369737ec4e1aSPeter Brune }
369837ec4e1aSPeter Brune 
36999b94acceSBarry Smith /*@
3700f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3701be5caee7SBarry Smith 
3702c3339decSBarry Smith   Logically Collective
3703be5caee7SBarry Smith 
3704be5caee7SBarry Smith   Input Parameters:
3705f6dfbefdSBarry Smith + snes  - the `SNES` context
3706f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3707be5caee7SBarry Smith 
3708f6dfbefdSBarry Smith   Options Database Key:
3709be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3710be5caee7SBarry Smith 
3711dc4c0fb0SBarry Smith   Level: intermediate
3712dc4c0fb0SBarry Smith 
3713f6dfbefdSBarry Smith   Note:
3714f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3715be5caee7SBarry Smith 
37161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
3717be5caee7SBarry Smith @*/
3718d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3719d71ae5a4SJacob Faibussowitsch {
3720be5caee7SBarry Smith   PetscFunctionBegin;
3721be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3722be5caee7SBarry Smith   snes->forceiteration = force;
37233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3724be5caee7SBarry Smith }
3725be5caee7SBarry Smith 
372685216dc7SFande Kong /*@
3727f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
372885216dc7SFande Kong 
3729c3339decSBarry Smith   Logically Collective
373085216dc7SFande Kong 
37312fe279fdSBarry Smith   Input Parameter:
3732f6dfbefdSBarry Smith . snes - the `SNES` context
373385216dc7SFande Kong 
373485216dc7SFande Kong   Output Parameter:
3735dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
373685216dc7SFande Kong 
373706dd6b0eSSatish Balay   Level: intermediate
373806dd6b0eSSatish Balay 
37391cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`
374085216dc7SFande Kong @*/
3741d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3742d71ae5a4SJacob Faibussowitsch {
374385216dc7SFande Kong   PetscFunctionBegin;
374485216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
374585216dc7SFande Kong   *force = snes->forceiteration;
37463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
374785216dc7SFande Kong }
3748be5caee7SBarry Smith 
3749be5caee7SBarry Smith /*@
3750f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
37519b94acceSBarry Smith 
3752c3339decSBarry Smith   Logically Collective
3753c7afd0dbSLois Curfman McInnes 
37549b94acceSBarry Smith   Input Parameters:
3755f6dfbefdSBarry Smith + snes   - the `SNES` context
375670441072SBarry Smith . abstol - absolute convergence tolerance
375733174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
37585358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3759f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
3760f6dfbefdSBarry Smith - maxf   - maximum number of function evaluations (-1 indicates no limit), default 1000
3761fee21e36SBarry Smith 
376233174efeSLois Curfman McInnes   Options Database Keys:
376370441072SBarry Smith + -snes_atol <abstol>    - Sets abstol
3764c7afd0dbSLois Curfman McInnes . -snes_rtol <rtol>      - Sets rtol
3765c7afd0dbSLois Curfman McInnes . -snes_stol <stol>      - Sets stol
3766c7afd0dbSLois Curfman McInnes . -snes_max_it <maxit>   - Sets maxit
3767c7afd0dbSLois Curfman McInnes - -snes_max_funcs <maxf> - Sets maxf
37689b94acceSBarry Smith 
376936851e7fSLois Curfman McInnes   Level: intermediate
377036851e7fSLois Curfman McInnes 
377100677de2SStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetTrustRegionTolerance()`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
37729b94acceSBarry Smith @*/
3773d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3774d71ae5a4SJacob Faibussowitsch {
37753a40ed3dSBarry Smith   PetscFunctionBegin;
37760700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3777c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3778c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3779c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3780c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3781c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3782c5eb9154SBarry Smith 
378313bcc0bdSJacob Faibussowitsch   if (abstol != (PetscReal)PETSC_DEFAULT) {
37845f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3785ab54825eSJed Brown     snes->abstol = abstol;
3786ab54825eSJed Brown   }
378713bcc0bdSJacob Faibussowitsch   if (rtol != (PetscReal)PETSC_DEFAULT) {
37885f80ce2aSJacob 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);
3789ab54825eSJed Brown     snes->rtol = rtol;
3790ab54825eSJed Brown   }
379113bcc0bdSJacob Faibussowitsch   if (stol != (PetscReal)PETSC_DEFAULT) {
37925f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3793c60f73f4SPeter Brune     snes->stol = stol;
3794ab54825eSJed Brown   }
3795ab54825eSJed Brown   if (maxit != PETSC_DEFAULT) {
379663a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3797ab54825eSJed Brown     snes->max_its = maxit;
3798ab54825eSJed Brown   }
3799ab54825eSJed Brown   if (maxf != PETSC_DEFAULT) {
380063a3b9bcSJacob Faibussowitsch     PetscCheck(maxf >= -1, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be -1 or nonnegative", maxf);
3801ab54825eSJed Brown     snes->max_funcs = maxf;
3802ab54825eSJed Brown   }
380388976e71SPeter Brune   snes->tolerancesset = PETSC_TRUE;
38043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38059b94acceSBarry Smith }
38069b94acceSBarry Smith 
3807e4d06f11SPatrick Farrell /*@
3808f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3809e4d06f11SPatrick Farrell 
3810c3339decSBarry Smith   Logically Collective
3811e4d06f11SPatrick Farrell 
3812e4d06f11SPatrick Farrell   Input Parameters:
3813f6dfbefdSBarry Smith + snes   - the `SNES` context
3814f6dfbefdSBarry Smith - divtol - the divergence tolerance. Use -1 to deactivate the test, default is 1e4
3815e4d06f11SPatrick Farrell 
3816f6dfbefdSBarry Smith   Options Database Key:
3817dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3818e4d06f11SPatrick Farrell 
3819e4d06f11SPatrick Farrell   Level: intermediate
3820e4d06f11SPatrick Farrell 
38211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance`
3822e4d06f11SPatrick Farrell @*/
3823d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3824d71ae5a4SJacob Faibussowitsch {
3825e4d06f11SPatrick Farrell   PetscFunctionBegin;
3826e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3827e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
3828e4d06f11SPatrick Farrell 
382913bcc0bdSJacob Faibussowitsch   if (divtol != (PetscReal)PETSC_DEFAULT) {
3830e4d06f11SPatrick Farrell     snes->divtol = divtol;
38319371c9d4SSatish Balay   } else {
3832e4d06f11SPatrick Farrell     snes->divtol = 1.0e4;
3833e4d06f11SPatrick Farrell   }
38343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3835e4d06f11SPatrick Farrell }
3836e4d06f11SPatrick Farrell 
38379b94acceSBarry Smith /*@
383833174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
383933174efeSLois Curfman McInnes 
3840c7afd0dbSLois Curfman McInnes   Not Collective
3841c7afd0dbSLois Curfman McInnes 
384233174efeSLois Curfman McInnes   Input Parameters:
3843f6dfbefdSBarry Smith + snes  - the `SNES` context
384485385478SLisandro Dalcin . atol  - absolute convergence tolerance
384533174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
384633174efeSLois Curfman McInnes . stol  - convergence tolerance in terms of the norm
384733174efeSLois Curfman McInnes           of the change in the solution between steps
384833174efeSLois Curfman McInnes . maxit - maximum number of iterations
3849c7afd0dbSLois Curfman McInnes - maxf  - maximum number of function evaluations
3850fee21e36SBarry Smith 
385136851e7fSLois Curfman McInnes   Level: intermediate
385236851e7fSLois Curfman McInnes 
3853dc4c0fb0SBarry Smith   Note:
3854dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3855dc4c0fb0SBarry Smith 
38561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
385733174efeSLois Curfman McInnes @*/
3858d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3859d71ae5a4SJacob Faibussowitsch {
38603a40ed3dSBarry Smith   PetscFunctionBegin;
38610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
386285385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
386333174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3864c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
386533174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
386633174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
38673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
386833174efeSLois Curfman McInnes }
386933174efeSLois Curfman McInnes 
3870e4d06f11SPatrick Farrell /*@
3871e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
3872e4d06f11SPatrick Farrell 
3873e4d06f11SPatrick Farrell   Not Collective
3874e4d06f11SPatrick Farrell 
3875e4d06f11SPatrick Farrell   Input Parameters:
3876f6dfbefdSBarry Smith + snes   - the `SNES` context
3877e4d06f11SPatrick Farrell - divtol - divergence tolerance
3878e4d06f11SPatrick Farrell 
3879e4d06f11SPatrick Farrell   Level: intermediate
3880e4d06f11SPatrick Farrell 
38811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
3882e4d06f11SPatrick Farrell @*/
3883d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
3884d71ae5a4SJacob Faibussowitsch {
3885e4d06f11SPatrick Farrell   PetscFunctionBegin;
3886e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3887e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
38883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3889e4d06f11SPatrick Farrell }
3890e4d06f11SPatrick Farrell 
389133174efeSLois Curfman McInnes /*@
38929b94acceSBarry Smith   SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance.
38939b94acceSBarry Smith 
3894c3339decSBarry Smith   Logically Collective
3895fee21e36SBarry Smith 
3896c7afd0dbSLois Curfman McInnes   Input Parameters:
3897f6dfbefdSBarry Smith + snes - the `SNES` context
3898c7afd0dbSLois Curfman McInnes - tol  - tolerance
3899c7afd0dbSLois Curfman McInnes 
39009b94acceSBarry Smith   Options Database Key:
39014a221d59SStefano Zampini . -snes_tr_tol <tol> - Sets tol
39029b94acceSBarry Smith 
390336851e7fSLois Curfman McInnes   Level: intermediate
390436851e7fSLois Curfman McInnes 
39059bcc50f1SBarry Smith   Developer Note:
39069bcc50f1SBarry Smith   Should be SNESTrustRegionSetTolerance()
39079bcc50f1SBarry Smith 
39081cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNEWTONTR`, `SNESSetTolerances()`
39099b94acceSBarry Smith @*/
3910d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTrustRegionTolerance(SNES snes, PetscReal tol)
3911d71ae5a4SJacob Faibussowitsch {
39123a40ed3dSBarry Smith   PetscFunctionBegin;
39130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3914c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, tol, 2);
39159b94acceSBarry Smith   snes->deltatol = tol;
39163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39179b94acceSBarry Smith }
39189b94acceSBarry Smith 
39196ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
39206ba87a44SLisandro Dalcin 
3921d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
3922d71ae5a4SJacob Faibussowitsch {
3923b271bb04SBarry Smith   PetscDrawLG      lg;
3924b271bb04SBarry Smith   PetscReal        x, y, per;
3925b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
3926b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
3927b271bb04SBarry Smith   PetscDraw        draw;
3928b271bb04SBarry Smith 
3929459f5d12SBarry Smith   PetscFunctionBegin;
39304d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
39319566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
39329566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39339566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39349566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
3935b271bb04SBarry Smith   x = (PetscReal)n;
393677b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
393794c9c6d3SKarl Rupp   else y = -15.0;
39389566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39396934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39409566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39419566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3942b271bb04SBarry Smith   }
3943b271bb04SBarry Smith 
39449566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
39459566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39469566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
3947aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
39489566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
3949b271bb04SBarry Smith   x = (PetscReal)n;
3950b271bb04SBarry Smith   y = 100.0 * per;
39519566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39526934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39539566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39549566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3955b271bb04SBarry Smith   }
3956b271bb04SBarry Smith 
39579566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
39589371c9d4SSatish Balay   if (!n) {
39599371c9d4SSatish Balay     prev = rnorm;
39609371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
39619371c9d4SSatish Balay   }
39629566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39639566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
3964b271bb04SBarry Smith   x = (PetscReal)n;
3965b271bb04SBarry Smith   y = (prev - rnorm) / prev;
39669566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
39676934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39689566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39699566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3970b271bb04SBarry Smith   }
3971b271bb04SBarry Smith 
39729566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
39739566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
39749566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
39759566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
3976b271bb04SBarry Smith   x = (PetscReal)n;
3977b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
3978b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
39799566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
3980b271bb04SBarry Smith   }
39816934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
39829566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
39839566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
3984b271bb04SBarry Smith   }
3985b271bb04SBarry Smith   prev = rnorm;
39863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3987b271bb04SBarry Smith }
3988b271bb04SBarry Smith 
3989228d79bcSJed Brown /*@
39902d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
39912d157150SStefano Zampini 
39922d157150SStefano Zampini   Collective
39932d157150SStefano Zampini 
39942d157150SStefano Zampini   Input Parameters:
39952d157150SStefano Zampini + snes  - the `SNES` context
39962d157150SStefano Zampini . it    - current iteration
39972d157150SStefano Zampini . xnorm - 2-norm of current iterate
39982d157150SStefano Zampini . snorm - 2-norm of current step
39992d157150SStefano Zampini - fnorm - 2-norm of function
40002d157150SStefano Zampini 
40012d157150SStefano Zampini   Level: developer
40022d157150SStefano Zampini 
40032d157150SStefano Zampini   Note:
4004420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
40052d157150SStefano Zampini   It does not typically need to be called by the user.
40062d157150SStefano Zampini 
4007be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
40082d157150SStefano Zampini @*/
40092d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
40102d157150SStefano Zampini {
40112d157150SStefano Zampini   PetscFunctionBegin;
40122d157150SStefano Zampini   if (!snes->reason) {
40132d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
40142d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
40152d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
40162d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
40172d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
40182d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
40192d157150SStefano Zampini     }
40202d157150SStefano Zampini   }
40212d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
40222d157150SStefano Zampini }
40232d157150SStefano Zampini 
40242d157150SStefano Zampini /*@
4025228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
4026228d79bcSJed Brown 
4027c3339decSBarry Smith   Collective
4028228d79bcSJed Brown 
4029228d79bcSJed Brown   Input Parameters:
4030f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
4031228d79bcSJed Brown . iter  - iteration number
4032228d79bcSJed Brown - rnorm - relative norm of the residual
4033228d79bcSJed Brown 
4034dc4c0fb0SBarry Smith   Level: developer
4035dc4c0fb0SBarry Smith 
4036f6dfbefdSBarry Smith   Note:
4037420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4038228d79bcSJed Brown   It does not typically need to be called by the user.
4039228d79bcSJed Brown 
40401cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4041228d79bcSJed Brown @*/
4042d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4043d71ae5a4SJacob Faibussowitsch {
40447a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
40457a03ce2fSLisandro Dalcin 
40467a03ce2fSLisandro Dalcin   PetscFunctionBegin;
40475f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
40489566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
404948a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
40509566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
40513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40527a03ce2fSLisandro Dalcin }
40537a03ce2fSLisandro Dalcin 
40549b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
40559b94acceSBarry Smith 
4056bf388a1fSBarry Smith /*MC
4057f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4058bf388a1fSBarry Smith 
4059bf388a1fSBarry Smith      Synopsis:
4060aaa7dc30SBarry Smith      #include <petscsnes.h>
406137fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4062bf388a1fSBarry Smith 
4063c3339decSBarry Smith      Collective
40641843f636SBarry Smith 
40651843f636SBarry Smith     Input Parameters:
4066f6dfbefdSBarry Smith +    snes - the `SNES` context
4067bf388a1fSBarry Smith .    its - iteration number
4068bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4069bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4070bf388a1fSBarry Smith 
4071878cb397SSatish Balay    Level: advanced
4072878cb397SSatish Balay 
40731cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4074bf388a1fSBarry Smith M*/
4075bf388a1fSBarry Smith 
40769b94acceSBarry Smith /*@C
4077a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
40789b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
40799b94acceSBarry Smith   progress.
40809b94acceSBarry Smith 
4081c3339decSBarry Smith   Logically Collective
4082fee21e36SBarry Smith 
4083c7afd0dbSLois Curfman McInnes   Input Parameters:
4084f6dfbefdSBarry Smith + snes           - the `SNES` context
408520f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4086420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4087dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
40889b94acceSBarry Smith 
40899665c990SLois Curfman McInnes   Options Database Keys:
4090f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4091798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4092dc4c0fb0SBarry 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
4093c7afd0dbSLois Curfman McInnes                                 the options database.
40949665c990SLois Curfman McInnes 
4095dc4c0fb0SBarry Smith   Level: intermediate
4096dc4c0fb0SBarry Smith 
4097f6dfbefdSBarry Smith   Note:
40986bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4099f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
41006bc08f3fSLois Curfman McInnes   order in which they were set.
4101639f9d9dSBarry Smith 
4102420bcc1bSBarry Smith   Fortran Note:
4103f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4104025f1a04SBarry Smith 
41051cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
41069b94acceSBarry Smith @*/
4107d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4108d71ae5a4SJacob Faibussowitsch {
4109b90d0a6eSBarry Smith   PetscInt  i;
411078064530SBarry Smith   PetscBool identical;
4111b90d0a6eSBarry Smith 
41123a40ed3dSBarry Smith   PetscFunctionBegin;
41130700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4114b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
41159566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
41163ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4117649052a6SBarry Smith   }
41185f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
41196e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4120b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4121639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
41223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41239b94acceSBarry Smith }
41249b94acceSBarry Smith 
4125a278d85bSSatish Balay /*@
4126f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
41275cd90555SBarry Smith 
4128c3339decSBarry Smith   Logically Collective
4129c7afd0dbSLois Curfman McInnes 
41302fe279fdSBarry Smith   Input Parameter:
4131f6dfbefdSBarry Smith . snes - the `SNES` context
41325cd90555SBarry Smith 
41331a480d89SAdministrator   Options Database Key:
4134a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4135dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4136c7afd0dbSLois Curfman McInnes     set via the options database
41375cd90555SBarry Smith 
4138dc4c0fb0SBarry Smith   Level: intermediate
4139dc4c0fb0SBarry Smith 
4140f6dfbefdSBarry Smith   Note:
4141f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
41425cd90555SBarry Smith 
41431cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
41445cd90555SBarry Smith @*/
4145d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4146d71ae5a4SJacob Faibussowitsch {
4147d952e501SBarry Smith   PetscInt i;
4148d952e501SBarry Smith 
41495cd90555SBarry Smith   PetscFunctionBegin;
41500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4151d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
415248a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4153d952e501SBarry Smith   }
41545cd90555SBarry Smith   snes->numbermonitors = 0;
41553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41565cd90555SBarry Smith }
41575cd90555SBarry Smith 
4158bf388a1fSBarry Smith /*MC
4159bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4160bf388a1fSBarry Smith 
4161bf388a1fSBarry Smith      Synopsis:
4162aaa7dc30SBarry Smith      #include <petscsnes.h>
416337fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4164bf388a1fSBarry Smith 
4165c3339decSBarry Smith      Collective
41661843f636SBarry Smith 
41671843f636SBarry Smith     Input Parameters:
4168f6dfbefdSBarry Smith +    snes - the `SNES` context
4169bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4170bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4171bf388a1fSBarry Smith .    gnorm - 2-norm of current step
41721843f636SBarry Smith .    f - 2-norm of function
41731843f636SBarry Smith -    cctx - [optional] convergence context
41741843f636SBarry Smith 
41751843f636SBarry Smith     Output Parameter:
41761843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4177bf388a1fSBarry Smith 
4178878cb397SSatish Balay    Level: intermediate
4179bf388a1fSBarry Smith 
41801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4181bf388a1fSBarry Smith M*/
4182bf388a1fSBarry Smith 
41839b94acceSBarry Smith /*@C
41849b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
41859b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
41869b94acceSBarry Smith 
4187c3339decSBarry Smith   Logically Collective
4188fee21e36SBarry Smith 
4189c7afd0dbSLois Curfman McInnes   Input Parameters:
4190f6dfbefdSBarry Smith + snes                        - the `SNES` context
4191e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4192dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4193dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
41949b94acceSBarry Smith 
419536851e7fSLois Curfman McInnes   Level: advanced
419636851e7fSLois Curfman McInnes 
41971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
41989b94acceSBarry Smith @*/
4199d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4200d71ae5a4SJacob Faibussowitsch {
42013a40ed3dSBarry Smith   PetscFunctionBegin;
42020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4203e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
42041baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4205bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
42067f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
420785385478SLisandro Dalcin   snes->cnvP                  = cctx;
42083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42099b94acceSBarry Smith }
42109b94acceSBarry Smith 
421152baeb72SSatish Balay /*@
4212f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4213184914b5SBarry Smith 
4214184914b5SBarry Smith   Not Collective
4215184914b5SBarry Smith 
4216184914b5SBarry Smith   Input Parameter:
4217f6dfbefdSBarry Smith . snes - the `SNES` context
4218184914b5SBarry Smith 
4219184914b5SBarry Smith   Output Parameter:
4220f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4221184914b5SBarry Smith 
4222f6dfbefdSBarry Smith   Options Database Key:
42236a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
42246a4d7782SBarry Smith 
4225184914b5SBarry Smith   Level: intermediate
4226184914b5SBarry Smith 
4227f6dfbefdSBarry Smith   Note:
4228f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4229184914b5SBarry Smith 
42301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4231184914b5SBarry Smith @*/
4232d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4233d71ae5a4SJacob Faibussowitsch {
4234184914b5SBarry Smith   PetscFunctionBegin;
42350700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42364f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4237184914b5SBarry Smith   *reason = snes->reason;
42383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4239184914b5SBarry Smith }
4240184914b5SBarry Smith 
4241c4421ceaSFande Kong /*@C
4242f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4243c4421ceaSFande Kong 
4244c4421ceaSFande Kong   Not Collective
4245c4421ceaSFande Kong 
4246c4421ceaSFande Kong   Input Parameter:
4247f6dfbefdSBarry Smith . snes - the `SNES` context
4248c4421ceaSFande Kong 
4249c4421ceaSFande Kong   Output Parameter:
4250dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4251c4421ceaSFande Kong 
425299c90e12SSatish Balay   Level: beginner
4253c4421ceaSFande Kong 
42541cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4255c4421ceaSFande Kong @*/
4256d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4257d71ae5a4SJacob Faibussowitsch {
4258c4421ceaSFande Kong   PetscFunctionBegin;
4259c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42604f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4261c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
42623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4263c4421ceaSFande Kong }
4264c4421ceaSFande Kong 
426533866048SMatthew G. Knepley /*@
4266f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
426733866048SMatthew G. Knepley 
426833866048SMatthew G. Knepley   Not Collective
426933866048SMatthew G. Knepley 
427033866048SMatthew G. Knepley   Input Parameters:
4271f6dfbefdSBarry Smith + snes   - the `SNES` context
4272f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
427333866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
427433866048SMatthew G. Knepley 
4275f6dfbefdSBarry Smith   Level: developer
4276f6dfbefdSBarry Smith 
4277420bcc1bSBarry Smith   Developer Note:
4278f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
427933866048SMatthew G. Knepley 
42801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
428133866048SMatthew G. Knepley @*/
4282d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4283d71ae5a4SJacob Faibussowitsch {
428433866048SMatthew G. Knepley   PetscFunctionBegin;
428533866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
42865f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
428733866048SMatthew G. Knepley   snes->reason = reason;
42883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
428933866048SMatthew G. Knepley }
429033866048SMatthew G. Knepley 
4291c9005455SLois Curfman McInnes /*@
4292420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4293c9005455SLois Curfman McInnes 
4294c3339decSBarry Smith   Logically Collective
4295fee21e36SBarry Smith 
4296c7afd0dbSLois Curfman McInnes   Input Parameters:
4297f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
42988c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4299cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4300420bcc1bSBarry Smith . na    - size of `a` and `its`
4301f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4302758f92a0SBarry Smith            else it continues storing new values for new nonlinear solves after the old ones
4303c7afd0dbSLois Curfman McInnes 
4304dc4c0fb0SBarry Smith   Level: intermediate
4305dc4c0fb0SBarry Smith 
4306308dcc3eSBarry Smith   Notes:
4307dc4c0fb0SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' `PETSC_DECIDE` or `PETSC_DEFAULT` then a
4308308dcc3eSBarry Smith   default array of length 10000 is allocated.
4309308dcc3eSBarry Smith 
4310c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4311c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4312c9005455SLois Curfman McInnes   during the section of code that is being timed.
4313c9005455SLois Curfman McInnes 
4314420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4315420bcc1bSBarry Smith 
43161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4317c9005455SLois Curfman McInnes @*/
4318d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4319d71ae5a4SJacob Faibussowitsch {
43203a40ed3dSBarry Smith   PetscFunctionBegin;
43210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43224f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
43234f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
43247a1ec6d4SBarry Smith   if (!a) {
4325308dcc3eSBarry Smith     if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000;
43269566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4327071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4328308dcc3eSBarry Smith   }
4329c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4330758f92a0SBarry Smith   snes->conv_hist_its   = its;
4331115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4332a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4333758f92a0SBarry Smith   snes->conv_hist_reset = reset;
43343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4335758f92a0SBarry Smith }
4336758f92a0SBarry Smith 
4337d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4338c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4339c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
434099e0435eSBarry Smith 
4341d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4342d71ae5a4SJacob Faibussowitsch {
4343308dcc3eSBarry Smith   mxArray   *mat;
4344308dcc3eSBarry Smith   PetscInt   i;
4345308dcc3eSBarry Smith   PetscReal *ar;
4346308dcc3eSBarry Smith 
4347308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4348308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4349f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
435011cc89d2SBarry Smith   return mat;
4351308dcc3eSBarry Smith }
4352308dcc3eSBarry Smith #endif
4353308dcc3eSBarry Smith 
43540c4c9dddSBarry Smith /*@C
4355420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4356758f92a0SBarry Smith 
43573f9fe445SBarry Smith   Not Collective
4358758f92a0SBarry Smith 
4359758f92a0SBarry Smith   Input Parameter:
4360f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4361758f92a0SBarry Smith 
4362758f92a0SBarry Smith   Output Parameters:
4363f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4364758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4365758f92a0SBarry Smith          negative if not converged) for each solve.
436620f4b53cSBarry Smith - na  - size of `a` and `its`
4367758f92a0SBarry Smith 
4368dc4c0fb0SBarry Smith   Level: intermediate
4369dc4c0fb0SBarry Smith 
437020f4b53cSBarry Smith   Note:
437120f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
437220f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
437320f4b53cSBarry Smith   during the section of code that is being timed.
437420f4b53cSBarry Smith 
4375420bcc1bSBarry Smith   Fortran Note:
4376758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4377dc4c0fb0SBarry Smith .vb
4378dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4379dc4c0fb0SBarry Smith .ve
4380758f92a0SBarry Smith 
43811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4382758f92a0SBarry Smith @*/
4383d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4384d71ae5a4SJacob Faibussowitsch {
4385758f92a0SBarry Smith   PetscFunctionBegin;
43860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4387758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4388758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4389115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
43903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4391c9005455SLois Curfman McInnes }
4392c9005455SLois Curfman McInnes 
4393ac226902SBarry Smith /*@C
439476b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4395eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
43967e4bb74cSBarry Smith   it is called just before the Jacobian is "evaluated".
439776b2cf59SMatthew Knepley 
4398c3339decSBarry Smith   Logically Collective
439976b2cf59SMatthew Knepley 
440076b2cf59SMatthew Knepley   Input Parameters:
4401a2b725a8SWilliam Gropp + snes - The nonlinear solver context
4402a2b725a8SWilliam Gropp - func - The function
440376b2cf59SMatthew Knepley 
440420f4b53cSBarry Smith   Calling sequence of `func`:
440520f4b53cSBarry Smith + snes - the nonlinear solver context
440620f4b53cSBarry Smith - step - The current step of the iteration
440776b2cf59SMatthew Knepley 
4408fe97e370SBarry Smith   Level: advanced
4409fe97e370SBarry Smith 
4410420bcc1bSBarry Smith   Notes:
4411f6dfbefdSBarry 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
4412f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
4413fe97e370SBarry Smith   This is not used by most users.
441476b2cf59SMatthew Knepley 
4415aaa8cc7dSPierre 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.
44166b7fb656SBarry Smith 
4417e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
4418db781477SPatrick Sanan          `SNESMonitorSet()`, `SNESSetDivergenceTest()`
441976b2cf59SMatthew Knepley @*/
44200b4db180SJacob Faibussowitsch PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES snes, PetscInt step))
4421d71ae5a4SJacob Faibussowitsch {
442276b2cf59SMatthew Knepley   PetscFunctionBegin;
44230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4424e7788613SBarry Smith   snes->ops->update = func;
44253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
442676b2cf59SMatthew Knepley }
442776b2cf59SMatthew Knepley 
4428*ffeef943SBarry Smith /*@
4429f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
44302a359c20SBarry Smith 
4431c3339decSBarry Smith   Collective
44322a359c20SBarry Smith 
4433e4094ef1SJacob Faibussowitsch   Input Parameters:
4434f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
44352a359c20SBarry Smith - viewer - the viewer to display the reason
44362a359c20SBarry Smith 
44372a359c20SBarry Smith   Options Database Keys:
4438ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4439ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4440eafd5ff0SAlex Lindsay 
4441420bcc1bSBarry Smith   Level: beginner
4442420bcc1bSBarry Smith 
4443f6dfbefdSBarry Smith   Note:
4444f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4445f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
44462a359c20SBarry Smith 
44471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4448f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4449f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4450db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
44512a359c20SBarry Smith @*/
4452d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4453d71ae5a4SJacob Faibussowitsch {
445475cca76cSMatthew G. Knepley   PetscViewerFormat format;
44552a359c20SBarry Smith   PetscBool         isAscii;
44562a359c20SBarry Smith 
44572a359c20SBarry Smith   PetscFunctionBegin;
445819a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
44599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
44602a359c20SBarry Smith   if (isAscii) {
44619566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
446265bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
446375cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
446475cca76cSMatthew G. Knepley       DM       dm;
446575cca76cSMatthew G. Knepley       Vec      u;
446675cca76cSMatthew G. Knepley       PetscDS  prob;
446775cca76cSMatthew G. Knepley       PetscInt Nf, f;
446895cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
446995cbbfd3SMatthew G. Knepley       void    **exactCtx;
447075cca76cSMatthew G. Knepley       PetscReal error;
447175cca76cSMatthew G. Knepley 
44729566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
44739566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
44749566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
44759566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
44769566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
44779566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
44789566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
44799566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
44809566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
448163a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
448275cca76cSMatthew G. Knepley     }
4483eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
44842a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
448563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
44862a359c20SBarry Smith       } else {
448763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44882a359c20SBarry Smith       }
4489eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
44902a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
449163a3b9bcSJacob 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));
44922a359c20SBarry Smith       } else {
449363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
44942a359c20SBarry Smith       }
44952a359c20SBarry Smith     }
449665bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
44972a359c20SBarry Smith   }
44983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44992a359c20SBarry Smith }
45002a359c20SBarry Smith 
4501c4421ceaSFande Kong /*@C
4502c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4503aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4504c4421ceaSFande Kong 
4505c3339decSBarry Smith   Logically Collective
4506c4421ceaSFande Kong 
4507c4421ceaSFande Kong   Input Parameters:
4508f6dfbefdSBarry Smith + snes              - the `SNES` context
4509420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4510420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4511420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`)
4512420bcc1bSBarry Smith 
4513420bcc1bSBarry Smith   Calling sequence of `f`:
4514420bcc1bSBarry Smith + snes - the `SNES` context
4515420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function
4516420bcc1bSBarry Smith 
4517420bcc1bSBarry Smith   Calling sequence of `reasonviewerdestroy`:
4518420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function
4519c4421ceaSFande Kong 
4520c4421ceaSFande Kong   Options Database Keys:
4521f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4522420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4523420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4524c4421ceaSFande Kong 
4525dc4c0fb0SBarry Smith   Level: intermediate
4526dc4c0fb0SBarry Smith 
4527f6dfbefdSBarry Smith   Note:
4528c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4529f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4530c4421ceaSFande Kong   order in which they were set.
4531c4421ceaSFande Kong 
45321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4533c4421ceaSFande Kong @*/
4534420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx))
4535d71ae5a4SJacob Faibussowitsch {
4536c4421ceaSFande Kong   PetscInt  i;
4537c4421ceaSFande Kong   PetscBool identical;
4538c4421ceaSFande Kong 
4539c4421ceaSFande Kong   PetscFunctionBegin;
4540c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4541c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
45429566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode(*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
45433ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4544c4421ceaSFande Kong   }
45455f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4546c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4547c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4548c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
45493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4550c4421ceaSFande Kong }
4551c4421ceaSFande Kong 
455291f3e32bSBarry Smith /*@
4553420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4554c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
45552a359c20SBarry Smith 
4556c3339decSBarry Smith   Collective
45572a359c20SBarry Smith 
45582fe279fdSBarry Smith   Input Parameter:
4559f6dfbefdSBarry Smith . snes - the `SNES` object
45602a359c20SBarry Smith 
4561f6dfbefdSBarry Smith   Level: advanced
45622a359c20SBarry Smith 
45631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4564f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
45652a359c20SBarry Smith @*/
4566d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4567d71ae5a4SJacob Faibussowitsch {
45682a359c20SBarry Smith   PetscViewer       viewer;
45692a359c20SBarry Smith   PetscBool         flg;
45702a359c20SBarry Smith   static PetscBool  incall = PETSC_FALSE;
45712a359c20SBarry Smith   PetscViewerFormat format;
4572c4421ceaSFande Kong   PetscInt          i;
45732a359c20SBarry Smith 
45742a359c20SBarry Smith   PetscFunctionBegin;
45753ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
45762a359c20SBarry Smith   incall = PETSC_TRUE;
4577c4421ceaSFande Kong 
4578c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
457948a46eb9SPierre Jolivet   for (i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4580c4421ceaSFande Kong 
4581c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
45829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &viewer, &format, &flg));
45832a359c20SBarry Smith   if (flg) {
45849566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, format));
45859566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonView(snes, viewer));
45869566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
4587cd791dc2SBarry Smith     PetscCall(PetscOptionsRestoreViewer(&viewer));
45882a359c20SBarry Smith   }
45892a359c20SBarry Smith   incall = PETSC_FALSE;
45903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45912a359c20SBarry Smith }
45922a359c20SBarry Smith 
4593487a658cSBarry Smith /*@
4594f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
45959b94acceSBarry Smith 
4596c3339decSBarry Smith   Collective
4597c7afd0dbSLois Curfman McInnes 
4598b2002411SLois Curfman McInnes   Input Parameters:
4599f6dfbefdSBarry Smith + snes - the `SNES` context
4600dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
460185385478SLisandro Dalcin - x    - the solution vector.
46029b94acceSBarry Smith 
4603dc4c0fb0SBarry Smith   Level: beginner
4604dc4c0fb0SBarry Smith 
4605f6dfbefdSBarry Smith   Note:
4606420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4607420bcc1bSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
46088ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4609f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
46108ddd3da0SLois Curfman McInnes 
46111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4612db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4613420bcc1bSBarry Smith           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
46149b94acceSBarry Smith @*/
4615d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4616d71ae5a4SJacob Faibussowitsch {
4617ace3abfcSBarry Smith   PetscBool flg;
4618efd51863SBarry Smith   PetscInt  grid;
46190298fd71SBarry Smith   Vec       xcreated = NULL;
4620caa4e7f2SJed Brown   DM        dm;
4621052efed2SBarry Smith 
46223a40ed3dSBarry Smith   PetscFunctionBegin;
46230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4624a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4625a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
46260700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
462785385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
462885385478SLisandro Dalcin 
462934b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
463006fc46c8SMatthew G. Knepley   {
463106fc46c8SMatthew G. Knepley     PetscViewer       viewer;
463206fc46c8SMatthew G. Knepley     PetscViewerFormat format;
46337c88af5aSMatthew G. Knepley     PetscInt          num;
463406fc46c8SMatthew G. Knepley     PetscBool         flg;
463506fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
463606fc46c8SMatthew G. Knepley 
463706fc46c8SMatthew G. Knepley     if (!incall) {
463834b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
46399566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
464006fc46c8SMatthew G. Knepley       if (flg) {
464106fc46c8SMatthew G. Knepley         PetscConvEst conv;
464246079b62SMatthew G. Knepley         DM           dm;
464346079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
464446079b62SMatthew G. Knepley         PetscInt     Nf;
464506fc46c8SMatthew G. Knepley 
464606fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
46479566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
46489566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
46499566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
46509566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
46519566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
46529566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
46539566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
46549566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
46559566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
46569566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
46579566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4658cd791dc2SBarry Smith         PetscCall(PetscOptionsRestoreViewer(&viewer));
46599566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
46609566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
466106fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
466206fc46c8SMatthew G. Knepley       }
466334b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4664b2588ea6SMatthew G. Knepley       num = 1;
46659566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
466634b4d3a8SMatthew G. Knepley       if (flg) {
466734b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
466834b4d3a8SMatthew G. Knepley 
466934b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
46709566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46719566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46729566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46739566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46749566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46759566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
46769566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
467734b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
467834b4d3a8SMatthew G. Knepley       }
46797c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
46807c88af5aSMatthew G. Knepley       num = 0;
46819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
46827c88af5aSMatthew G. Knepley       if (num) {
46837c88af5aSMatthew G. Knepley         DMAdaptor adaptor;
46847c88af5aSMatthew G. Knepley 
46857c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
46869566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
46879566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
46889566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
46899566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
46909566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
46919566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
46929566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
46937c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
46947c88af5aSMatthew G. Knepley       }
469506fc46c8SMatthew G. Knepley     }
469606fc46c8SMatthew G. Knepley   }
4697ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4698caa4e7f2SJed Brown   if (!x) {
46999566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
47009566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4701a69afd8bSBarry Smith     x = xcreated;
4702a69afd8bSBarry Smith   }
47039566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4704f05ece33SBarry Smith 
47059566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4706efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
470785385478SLisandro Dalcin     /* set solution vector */
47089566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
47099566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
471085385478SLisandro Dalcin     snes->vec_sol = x;
47119566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4712caa4e7f2SJed Brown 
4713caa4e7f2SJed Brown     /* set affine vector if provided */
47149566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
47159566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
471685385478SLisandro Dalcin     snes->vec_rhs = b;
471785385478SLisandro Dalcin 
47185f80ce2aSJacob 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");
47195f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4720dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4721aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
47229566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
47239566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
47243f149594SLisandro Dalcin 
47257eee914bSBarry Smith     if (!grid) {
47269927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4727dd568438SSatish Balay     }
4728d25893d9SBarry Smith 
4729abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
47309371c9d4SSatish Balay     if (snes->counters_reset) {
47319371c9d4SSatish Balay       snes->nfuncs      = 0;
47329371c9d4SSatish Balay       snes->linear_its  = 0;
47339371c9d4SSatish Balay       snes->numFailures = 0;
47349371c9d4SSatish Balay     }
4735d5e45103SBarry Smith 
47362d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
47379566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4738dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
47399566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
47402d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4741422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
47423f149594SLisandro Dalcin 
474337ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
474437ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
474537ec4e1aSPeter Brune 
47469566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
47479566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4748c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
47499566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
47505968eb51SBarry Smith 
47515f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
47529c8e83a9SBarry Smith     if (snes->reason < 0) break;
4753efd51863SBarry Smith     if (grid < snes->gridsequence) {
4754efd51863SBarry Smith       DM  fine;
4755efd51863SBarry Smith       Vec xnew;
4756efd51863SBarry Smith       Mat interp;
4757efd51863SBarry Smith 
47589566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
47595f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
47609566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
47619566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
47629566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
47639566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
47649566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4765efd51863SBarry Smith       x = xnew;
4766efd51863SBarry Smith 
47679566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
47689566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
47699566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
47709566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
47719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4772efd51863SBarry Smith     }
4773efd51863SBarry Smith   }
47749566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
47759566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
47769566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
47779566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
47783f7e2da0SPeter Brune 
47799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
47809566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
47813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47829b94acceSBarry Smith }
47839b94acceSBarry Smith 
47849b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
47859b94acceSBarry Smith 
4786cc4c1da9SBarry Smith /*@
47874b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
47889b94acceSBarry Smith 
4789c3339decSBarry Smith   Collective
4790fee21e36SBarry Smith 
4791c7afd0dbSLois Curfman McInnes   Input Parameters:
4792f6dfbefdSBarry Smith + snes - the `SNES` context
4793454a90a3SBarry Smith - type - a known method
4794c7afd0dbSLois Curfman McInnes 
4795c7afd0dbSLois Curfman McInnes   Options Database Key:
4796454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
479704d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4798ae12b187SLois Curfman McInnes 
4799dc4c0fb0SBarry Smith   Level: intermediate
4800dc4c0fb0SBarry Smith 
48019b94acceSBarry Smith   Notes:
4802e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4803f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4804c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
48054a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4806c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
48079b94acceSBarry Smith 
4808f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4809f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4810ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4811ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4812f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4813ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4814ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4815ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4816ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4817b0a32e0cSBarry Smith   appropriate method.
481836851e7fSLois Curfman McInnes 
4819420bcc1bSBarry Smith   Developer Note:
4820f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4821f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
48228f6c3df8SBarry Smith 
48231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
48249b94acceSBarry Smith @*/
4825d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4826d71ae5a4SJacob Faibussowitsch {
4827ace3abfcSBarry Smith   PetscBool match;
48285f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
48293a40ed3dSBarry Smith 
48303a40ed3dSBarry Smith   PetscFunctionBegin;
48310700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48324f572ea9SToby Isaac   PetscAssertPointer(type, 2);
483382bf6240SBarry Smith 
48349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
48353ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
483692ff6ae8SBarry Smith 
48379566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
48386adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
483975396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4840dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
484175396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
48429e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
48439e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
48449e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
48459e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
48469e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
48477fe760d5SStefano Zampini 
48487fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
48499566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
48507fe760d5SStefano Zampini 
485175396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
485275396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4853f5af7f23SKarl Rupp 
48549566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
48559566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
48563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48579b94acceSBarry Smith }
48589b94acceSBarry Smith 
4859cc4c1da9SBarry Smith /*@
4860f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
48619b94acceSBarry Smith 
4862c7afd0dbSLois Curfman McInnes   Not Collective
4863c7afd0dbSLois Curfman McInnes 
48649b94acceSBarry Smith   Input Parameter:
48654b0e389bSBarry Smith . snes - nonlinear solver context
48669b94acceSBarry Smith 
48679b94acceSBarry Smith   Output Parameter:
4868f6dfbefdSBarry Smith . type - `SNES` method (a character string)
48699b94acceSBarry Smith 
487036851e7fSLois Curfman McInnes   Level: intermediate
487136851e7fSLois Curfman McInnes 
48721cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
48739b94acceSBarry Smith @*/
4874d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4875d71ae5a4SJacob Faibussowitsch {
48763a40ed3dSBarry Smith   PetscFunctionBegin;
48770700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
48784f572ea9SToby Isaac   PetscAssertPointer(type, 2);
48797adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
48803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48819b94acceSBarry Smith }
48829b94acceSBarry Smith 
48833cd8a7caSMatthew G. Knepley /*@
4884f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
48853cd8a7caSMatthew G. Knepley 
4886c3339decSBarry Smith   Logically Collective
48873cd8a7caSMatthew G. Knepley 
48883cd8a7caSMatthew G. Knepley   Input Parameters:
4889f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
48903cd8a7caSMatthew G. Knepley - u    - the solution vector
48913cd8a7caSMatthew G. Knepley 
48923cd8a7caSMatthew G. Knepley   Level: beginner
48933cd8a7caSMatthew G. Knepley 
48941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
48953cd8a7caSMatthew G. Knepley @*/
4896d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4897d71ae5a4SJacob Faibussowitsch {
48983cd8a7caSMatthew G. Knepley   DM dm;
48993cd8a7caSMatthew G. Knepley 
49003cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
49013cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49023cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
49039566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
49049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
49053cd8a7caSMatthew G. Knepley 
49063cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
49073cd8a7caSMatthew G. Knepley 
49089566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
49099566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
49103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49113cd8a7caSMatthew G. Knepley }
49123cd8a7caSMatthew G. Knepley 
491352baeb72SSatish Balay /*@
49149b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
4915f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
49169b94acceSBarry Smith 
4917420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4918c7afd0dbSLois Curfman McInnes 
49199b94acceSBarry Smith   Input Parameter:
4920f6dfbefdSBarry Smith . snes - the `SNES` context
49219b94acceSBarry Smith 
49229b94acceSBarry Smith   Output Parameter:
49239b94acceSBarry Smith . x - the solution
49249b94acceSBarry Smith 
492570e92668SMatthew Knepley   Level: intermediate
492636851e7fSLois Curfman McInnes 
49271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
49289b94acceSBarry Smith @*/
4929d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
4930d71ae5a4SJacob Faibussowitsch {
49313a40ed3dSBarry Smith   PetscFunctionBegin;
49320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49334f572ea9SToby Isaac   PetscAssertPointer(x, 2);
493485385478SLisandro Dalcin   *x = snes->vec_sol;
49353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
493670e92668SMatthew Knepley }
493770e92668SMatthew Knepley 
493852baeb72SSatish Balay /*@
49399b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
49409b94acceSBarry Smith   stored.
49419b94acceSBarry Smith 
4942420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
4943c7afd0dbSLois Curfman McInnes 
49449b94acceSBarry Smith   Input Parameter:
4945f6dfbefdSBarry Smith . snes - the `SNES` context
49469b94acceSBarry Smith 
49479b94acceSBarry Smith   Output Parameter:
49489b94acceSBarry Smith . x - the solution update
49499b94acceSBarry Smith 
495036851e7fSLois Curfman McInnes   Level: advanced
495136851e7fSLois Curfman McInnes 
49521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
49539b94acceSBarry Smith @*/
4954d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
4955d71ae5a4SJacob Faibussowitsch {
49563a40ed3dSBarry Smith   PetscFunctionBegin;
49570700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49584f572ea9SToby Isaac   PetscAssertPointer(x, 2);
495985385478SLisandro Dalcin   *x = snes->vec_sol_update;
49603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49619b94acceSBarry Smith }
49629b94acceSBarry Smith 
49639b94acceSBarry Smith /*@C
4964f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
49659b94acceSBarry Smith 
4966420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
4967c7afd0dbSLois Curfman McInnes 
49689b94acceSBarry Smith   Input Parameter:
4969f6dfbefdSBarry Smith . snes - the `SNES` context
49709b94acceSBarry Smith 
4971d8d19677SJose E. Roman   Output Parameters:
4972dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
49738434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
4974dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
49759b94acceSBarry Smith 
497636851e7fSLois Curfman McInnes   Level: advanced
497736851e7fSLois Curfman McInnes 
4978f6dfbefdSBarry Smith   Note:
4979dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
498004edfde5SBarry Smith 
49818434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
49829b94acceSBarry Smith @*/
49838434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
4984d71ae5a4SJacob Faibussowitsch {
49856cab3a1bSJed Brown   DM dm;
4986a63bb30eSJed Brown 
49873a40ed3dSBarry Smith   PetscFunctionBegin;
49880700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4989a63bb30eSJed Brown   if (r) {
4990a63bb30eSJed Brown     if (!snes->vec_func) {
4991a63bb30eSJed Brown       if (snes->vec_rhs) {
49929566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
4993a63bb30eSJed Brown       } else if (snes->vec_sol) {
49949566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
4995a63bb30eSJed Brown       } else if (snes->dm) {
49969566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
4997a63bb30eSJed Brown       }
4998a63bb30eSJed Brown     }
4999a63bb30eSJed Brown     *r = snes->vec_func;
5000a63bb30eSJed Brown   }
50019566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50029566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
50033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50049b94acceSBarry Smith }
50059b94acceSBarry Smith 
5006c79ef259SPeter Brune /*@C
500737fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5008c79ef259SPeter Brune 
5009c79ef259SPeter Brune   Input Parameter:
5010f6dfbefdSBarry Smith . snes - the `SNES` context
5011c79ef259SPeter Brune 
5012d8d19677SJose E. Roman   Output Parameters:
50138434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5014dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5015c79ef259SPeter Brune 
5016c79ef259SPeter Brune   Level: advanced
5017c79ef259SPeter Brune 
50188434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5019c79ef259SPeter Brune @*/
50208434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5021d71ae5a4SJacob Faibussowitsch {
50226cab3a1bSJed Brown   DM dm;
50236cab3a1bSJed Brown 
5024646217ecSPeter Brune   PetscFunctionBegin;
5025646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50269566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50279566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
50283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5029646217ecSPeter Brune }
5030646217ecSPeter Brune 
5031cc4c1da9SBarry Smith /*@
50323c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5033f6dfbefdSBarry Smith   `SNES` options in the database.
50343c7409f5SSatish Balay 
5035c3339decSBarry Smith   Logically Collective
5036fee21e36SBarry Smith 
5037d8d19677SJose E. Roman   Input Parameters:
5038f6dfbefdSBarry Smith + snes   - the `SNES` context
5039c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5040c7afd0dbSLois Curfman McInnes 
5041dc4c0fb0SBarry Smith   Level: advanced
5042dc4c0fb0SBarry Smith 
5043f6dfbefdSBarry Smith   Note:
5044a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5045c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5046d850072dSLois Curfman McInnes 
50471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
50483c7409f5SSatish Balay @*/
5049d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5050d71ae5a4SJacob Faibussowitsch {
50513a40ed3dSBarry Smith   PetscFunctionBegin;
50520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50539566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
50549566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
505535f5d045SPeter Brune   if (snes->linesearch) {
50569566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
505835f5d045SPeter Brune   }
50599566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
50603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50613c7409f5SSatish Balay }
50623c7409f5SSatish Balay 
5063cc4c1da9SBarry Smith /*@
5064f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5065f6dfbefdSBarry Smith   `SNES` options in the database.
50663c7409f5SSatish Balay 
5067c3339decSBarry Smith   Logically Collective
5068fee21e36SBarry Smith 
5069c7afd0dbSLois Curfman McInnes   Input Parameters:
5070f6dfbefdSBarry Smith + snes   - the `SNES` context
5071c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5072c7afd0dbSLois Curfman McInnes 
5073dc4c0fb0SBarry Smith   Level: advanced
5074dc4c0fb0SBarry Smith 
5075f6dfbefdSBarry Smith   Note:
5076a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5077c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5078d850072dSLois Curfman McInnes 
50791cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
50803c7409f5SSatish Balay @*/
5081d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5082d71ae5a4SJacob Faibussowitsch {
50833a40ed3dSBarry Smith   PetscFunctionBegin;
50840700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50859566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
50869566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
508735f5d045SPeter Brune   if (snes->linesearch) {
50889566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
50899566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
509035f5d045SPeter Brune   }
50919566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
50923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50933c7409f5SSatish Balay }
50943c7409f5SSatish Balay 
5095cc4c1da9SBarry Smith /*@
5096f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5097f6dfbefdSBarry Smith   `SNES` options in the database.
50983c7409f5SSatish Balay 
5099c7afd0dbSLois Curfman McInnes   Not Collective
5100c7afd0dbSLois Curfman McInnes 
51013c7409f5SSatish Balay   Input Parameter:
5102f6dfbefdSBarry Smith . snes - the `SNES` context
51033c7409f5SSatish Balay 
51043c7409f5SSatish Balay   Output Parameter:
51053c7409f5SSatish Balay . prefix - pointer to the prefix string used
51063c7409f5SSatish Balay 
510736851e7fSLois Curfman McInnes   Level: advanced
510836851e7fSLois Curfman McInnes 
5109420bcc1bSBarry Smith   Fortran Note:
5110dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5111dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5112dc4c0fb0SBarry Smith 
51131cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
51143c7409f5SSatish Balay @*/
5115d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5116d71ae5a4SJacob Faibussowitsch {
51173a40ed3dSBarry Smith   PetscFunctionBegin;
51180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51199566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
51203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51213c7409f5SSatish Balay }
51223c7409f5SSatish Balay 
51233cea93caSBarry Smith /*@C
51241c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
51251c84c290SBarry Smith 
512620f4b53cSBarry Smith   Not Collective
51271c84c290SBarry Smith 
51281c84c290SBarry Smith   Input Parameters:
512920f4b53cSBarry Smith + sname    - name of a new user-defined solver
513020f4b53cSBarry Smith - function - routine to create method context
51311c84c290SBarry Smith 
5132dc4c0fb0SBarry Smith   Level: advanced
5133dc4c0fb0SBarry Smith 
5134f6dfbefdSBarry Smith   Note:
5135f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
51361c84c290SBarry Smith 
5137e4094ef1SJacob Faibussowitsch   Example Usage:
51381c84c290SBarry Smith .vb
5139bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
51401c84c290SBarry Smith .ve
51411c84c290SBarry Smith 
51421c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
51431c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
51441c84c290SBarry Smith   or at runtime via the option
51451c84c290SBarry Smith $     -snes_type my_solver
51461c84c290SBarry Smith 
51471cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
51483cea93caSBarry Smith @*/
5149d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5150d71ae5a4SJacob Faibussowitsch {
5151b2002411SLois Curfman McInnes   PetscFunctionBegin;
51529566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
51539566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
51543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5155b2002411SLois Curfman McInnes }
5156da9b6338SBarry Smith 
5157d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5158d71ae5a4SJacob Faibussowitsch {
515977431f27SBarry Smith   PetscInt    N, i, j;
5160da9b6338SBarry Smith   Vec         u, uh, fh;
5161da9b6338SBarry Smith   PetscScalar value;
5162da9b6338SBarry Smith   PetscReal   norm;
5163da9b6338SBarry Smith 
5164da9b6338SBarry Smith   PetscFunctionBegin;
51659566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
51669566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
51679566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5168da9b6338SBarry Smith 
5169da9b6338SBarry Smith   /* currently only works for sequential */
51709566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
51719566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5172da9b6338SBarry Smith   for (i = 0; i < N; i++) {
51739566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
517463a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5175da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
51768b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
51779566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
51789566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
51799566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
518063a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5181da9b6338SBarry Smith       value = -value;
51829566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5183da9b6338SBarry Smith     }
5184da9b6338SBarry Smith   }
51859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
51869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
51873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5188da9b6338SBarry Smith }
518971f87433Sdalcinl 
519071f87433Sdalcinl /*@
5191f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
519271f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
519371f87433Sdalcinl   Newton method.
519471f87433Sdalcinl 
5195c3339decSBarry Smith   Logically Collective
519671f87433Sdalcinl 
519771f87433Sdalcinl   Input Parameters:
5198f6dfbefdSBarry Smith + snes - `SNES` context
5199f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
520071f87433Sdalcinl 
5201f6dfbefdSBarry Smith   Options Database Keys:
520264ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
520364ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
520464ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
520564ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
520664ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
520764ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
520864ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
520964ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
521064ba62caSBarry Smith 
5211dc4c0fb0SBarry Smith   Level: advanced
5212dc4c0fb0SBarry Smith 
5213f6dfbefdSBarry Smith   Note:
5214f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
521571f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
52161d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
521771f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
521871f87433Sdalcinl   solver.
521971f87433Sdalcinl 
52201cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
522171f87433Sdalcinl @*/
5222d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5223d71ae5a4SJacob Faibussowitsch {
522471f87433Sdalcinl   PetscFunctionBegin;
52250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5226acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
522771f87433Sdalcinl   snes->ksp_ewconv = flag;
52283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
522971f87433Sdalcinl }
523071f87433Sdalcinl 
523171f87433Sdalcinl /*@
5232f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
523371f87433Sdalcinl   for computing relative tolerance for linear solvers within an
523471f87433Sdalcinl   inexact Newton method.
523571f87433Sdalcinl 
523671f87433Sdalcinl   Not Collective
523771f87433Sdalcinl 
523871f87433Sdalcinl   Input Parameter:
5239f6dfbefdSBarry Smith . snes - `SNES` context
524071f87433Sdalcinl 
524171f87433Sdalcinl   Output Parameter:
5242f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
524371f87433Sdalcinl 
524471f87433Sdalcinl   Level: advanced
524571f87433Sdalcinl 
52461cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
524771f87433Sdalcinl @*/
5248d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5249d71ae5a4SJacob Faibussowitsch {
525071f87433Sdalcinl   PetscFunctionBegin;
52510700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52524f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
525371f87433Sdalcinl   *flag = snes->ksp_ewconv;
52543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
525571f87433Sdalcinl }
525671f87433Sdalcinl 
525771f87433Sdalcinl /*@
5258fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
525971f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
526071f87433Sdalcinl   Newton method.
526171f87433Sdalcinl 
5262c3339decSBarry Smith   Logically Collective
526371f87433Sdalcinl 
526471f87433Sdalcinl   Input Parameters:
5265f6dfbefdSBarry Smith + snes      - `SNES` context
52660f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
526771f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
526871f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
526971f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
527071f87433Sdalcinl              (0 <= gamma2 <= 1)
527171f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
527271f87433Sdalcinl . alpha2    - power for safeguard
527371f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
527471f87433Sdalcinl 
5275dc4c0fb0SBarry Smith   Level: advanced
5276dc4c0fb0SBarry Smith 
5277f6dfbefdSBarry Smith   Notes:
527871f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
527971f87433Sdalcinl 
5280f6dfbefdSBarry Smith   Use `PETSC_DEFAULT` to retain the default for any of the parameters.
528171f87433Sdalcinl 
52821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
528371f87433Sdalcinl @*/
5284d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5285d71ae5a4SJacob Faibussowitsch {
5286fa9f3622SBarry Smith   SNESKSPEW *kctx;
52875fd66863SKarl Rupp 
528871f87433Sdalcinl   PetscFunctionBegin;
52890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5290fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
52915f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5292c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5293c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5294c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5295c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5296c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5297c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5298c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
529971f87433Sdalcinl 
530071f87433Sdalcinl   if (version != PETSC_DEFAULT) kctx->version = version;
530113bcc0bdSJacob Faibussowitsch   if (rtol_0 != (PetscReal)PETSC_DEFAULT) kctx->rtol_0 = rtol_0;
530213bcc0bdSJacob Faibussowitsch   if (rtol_max != (PetscReal)PETSC_DEFAULT) kctx->rtol_max = rtol_max;
530313bcc0bdSJacob Faibussowitsch   if (gamma != (PetscReal)PETSC_DEFAULT) kctx->gamma = gamma;
530413bcc0bdSJacob Faibussowitsch   if (alpha != (PetscReal)PETSC_DEFAULT) kctx->alpha = alpha;
530513bcc0bdSJacob Faibussowitsch   if (alpha2 != (PetscReal)PETSC_DEFAULT) kctx->alpha2 = alpha2;
530613bcc0bdSJacob Faibussowitsch   if (threshold != (PetscReal)PETSC_DEFAULT) kctx->threshold = threshold;
530771f87433Sdalcinl 
53080f0abf79SStefano 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);
53090b121fc5SBarry 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);
53100b121fc5SBarry 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);
53110b121fc5SBarry 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);
53120b121fc5SBarry 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);
53130b121fc5SBarry 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);
53143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
531571f87433Sdalcinl }
531671f87433Sdalcinl 
531771f87433Sdalcinl /*@
5318fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
531971f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
532071f87433Sdalcinl   Newton method.
532171f87433Sdalcinl 
532271f87433Sdalcinl   Not Collective
532371f87433Sdalcinl 
532497bb3fdcSJose E. Roman   Input Parameter:
5325f6dfbefdSBarry Smith . snes - `SNES` context
532671f87433Sdalcinl 
532771f87433Sdalcinl   Output Parameters:
53280f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
532971f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
533071f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5331bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
533271f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
533371f87433Sdalcinl . alpha2    - power for safeguard
533471f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
533571f87433Sdalcinl 
533671f87433Sdalcinl   Level: advanced
533771f87433Sdalcinl 
53381cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
533971f87433Sdalcinl @*/
5340d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5341d71ae5a4SJacob Faibussowitsch {
5342fa9f3622SBarry Smith   SNESKSPEW *kctx;
53435fd66863SKarl Rupp 
534471f87433Sdalcinl   PetscFunctionBegin;
53450700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5346fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53475f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
534871f87433Sdalcinl   if (version) *version = kctx->version;
534971f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
535071f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
535171f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
535271f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
535371f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
535471f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
53553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
535671f87433Sdalcinl }
535771f87433Sdalcinl 
53585c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5359d71ae5a4SJacob Faibussowitsch {
53605c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5361fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
536271f87433Sdalcinl   PetscReal  rtol = PETSC_DEFAULT, stol;
536371f87433Sdalcinl 
536471f87433Sdalcinl   PetscFunctionBegin;
53653ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
536630058271SDmitry Karpeev   if (!snes->iter) {
536730058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
53689566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
53690f0abf79SStefano Zampini   } else {
53700fdf79fbSJacob 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);
537171f87433Sdalcinl     if (kctx->version == 1) {
53720f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
537385ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
537471f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
537571f87433Sdalcinl     } else if (kctx->version == 2) {
537685ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
537785ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
537871f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
537971f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
538085ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
538171f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
538285ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
538371f87433Sdalcinl       stol = PetscMax(rtol, stol);
538471f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
538571f87433Sdalcinl       /* safeguard: avoid oversolving */
538630058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
538771f87433Sdalcinl       stol = PetscMax(rtol, stol);
538871f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
53890fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
53900fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
53910f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
53920f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
53930f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
53940f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
53950f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
53960f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
53970f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
53980f0abf79SStefano Zampini 
5399a4598233SStefano 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;
54000f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
54010f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
54020f0abf79SStefano Zampini       kctx->rk_last     = rk;
54030fdf79fbSJacob Faibussowitsch     }
54040f0abf79SStefano Zampini   }
54050f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
540671f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
54079566063dSJacob Faibussowitsch   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
540863a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
54093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
541071f87433Sdalcinl }
541171f87433Sdalcinl 
54125c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5413d71ae5a4SJacob Faibussowitsch {
54145c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5415fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
541671f87433Sdalcinl   PCSide     pcside;
541771f87433Sdalcinl   Vec        lres;
541871f87433Sdalcinl 
541971f87433Sdalcinl   PetscFunctionBegin;
54203ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
54219566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
542271dbe336SPeter Brune   kctx->norm_last = snes->norm;
54230f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
54244f00ce20SMatthew G. Knepley     PC        pc;
54250f0abf79SStefano Zampini     PetscBool getRes;
54264f00ce20SMatthew G. Knepley 
54279566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
54280f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
54290f0abf79SStefano Zampini     if (!getRes) {
54300f0abf79SStefano Zampini       KSPNormType normtype;
54310f0abf79SStefano Zampini 
54320f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
54330f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
54340f0abf79SStefano Zampini     }
54359566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
54360f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
54379566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
543871f87433Sdalcinl     } else {
543971f87433Sdalcinl       /* KSP residual is preconditioned residual */
544071f87433Sdalcinl       /* compute true linear residual norm */
54410f0abf79SStefano Zampini       Mat J;
54420f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
54439566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
54440f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
54459566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
54469566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
54479566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
544871f87433Sdalcinl     }
544971f87433Sdalcinl   }
54503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545171f87433Sdalcinl }
545271f87433Sdalcinl 
5453d4211eb9SBarry Smith /*@
5454f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5455d4211eb9SBarry Smith 
5456420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5457d4211eb9SBarry Smith 
5458d4211eb9SBarry Smith   Input Parameter:
5459f6dfbefdSBarry Smith . snes - the `SNES` context
5460d4211eb9SBarry Smith 
5461d4211eb9SBarry Smith   Output Parameter:
5462f6dfbefdSBarry Smith . ksp - the `KSP` context
5463d4211eb9SBarry Smith 
5464dc4c0fb0SBarry Smith   Level: beginner
5465dc4c0fb0SBarry Smith 
5466d4211eb9SBarry Smith   Notes:
5467f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5468d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5469f6dfbefdSBarry Smith   `PC` contexts as well.
5470f6dfbefdSBarry Smith 
5471f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5472d4211eb9SBarry Smith 
54731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5474d4211eb9SBarry Smith @*/
5475d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5476d71ae5a4SJacob Faibussowitsch {
547771f87433Sdalcinl   PetscFunctionBegin;
5478d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
54794f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5480d4211eb9SBarry Smith 
5481d4211eb9SBarry Smith   if (!snes->ksp) {
54829566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
54839566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5484d4211eb9SBarry Smith 
54855c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
54865c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5487a5c2985bSBarry Smith 
54889566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
54899566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5490d4211eb9SBarry Smith   }
5491d4211eb9SBarry Smith   *ksp = snes->ksp;
54923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
549371f87433Sdalcinl }
54946c699258SBarry Smith 
5495af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
54966c699258SBarry Smith /*@
5497f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
54986c699258SBarry Smith 
5499c3339decSBarry Smith   Logically Collective
55006c699258SBarry Smith 
55016c699258SBarry Smith   Input Parameters:
55022a808120SBarry Smith + snes - the nonlinear solver context
5503420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5504dc4c0fb0SBarry Smith 
5505dc4c0fb0SBarry Smith   Level: intermediate
55066c699258SBarry Smith 
5507f6dfbefdSBarry Smith   Note:
5508f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5509f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5510e03a659cSJed Brown   problems using the same function space.
5511e03a659cSJed Brown 
5512420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
55136c699258SBarry Smith @*/
5514d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5515d71ae5a4SJacob Faibussowitsch {
5516345fed2cSBarry Smith   KSP    ksp;
5517942e3340SBarry Smith   DMSNES sdm;
55186c699258SBarry Smith 
55196c699258SBarry Smith   PetscFunctionBegin;
55200700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55212a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
55229566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5523942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
552451f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
55259566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
55269566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5527f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
55286cab3a1bSJed Brown     }
55299566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
55309566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
55316cab3a1bSJed Brown   }
55326c699258SBarry Smith   snes->dm     = dm;
5533116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5534f5af7f23SKarl Rupp 
55359566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
55369566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
55379566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5538efd4aadfSBarry Smith   if (snes->npc) {
55399566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
55409566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
55412c155ee1SBarry Smith   }
55423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55436c699258SBarry Smith }
55446c699258SBarry Smith 
55456c699258SBarry Smith /*@
5546420bcc1bSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners
55476c699258SBarry Smith 
5548f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
55496c699258SBarry Smith 
55506c699258SBarry Smith   Input Parameter:
5551420bcc1bSBarry Smith . snes - the `SNES` context
55526c699258SBarry Smith 
55536c699258SBarry Smith   Output Parameter:
5554420bcc1bSBarry Smith . dm - the `DM`
55556c699258SBarry Smith 
55566c699258SBarry Smith   Level: intermediate
55576c699258SBarry Smith 
5558420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
55596c699258SBarry Smith @*/
5560d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5561d71ae5a4SJacob Faibussowitsch {
55626c699258SBarry Smith   PetscFunctionBegin;
55630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55646cab3a1bSJed Brown   if (!snes->dm) {
55659566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5566116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
55676cab3a1bSJed Brown   }
55686c699258SBarry Smith   *dm = snes->dm;
55693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55706c699258SBarry Smith }
55710807856dSBarry Smith 
557231823bd8SMatthew G Knepley /*@
5573be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
557431823bd8SMatthew G Knepley 
5575c3339decSBarry Smith   Collective
557631823bd8SMatthew G Knepley 
557731823bd8SMatthew G Knepley   Input Parameters:
5578f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5579420bcc1bSBarry Smith - npc  - the nonlinear preconditioner object
558031823bd8SMatthew G Knepley 
5581dc4c0fb0SBarry Smith   Level: developer
5582dc4c0fb0SBarry Smith 
558331823bd8SMatthew G Knepley   Notes:
5584f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
558531823bd8SMatthew G Knepley   to configure it using the API).
558631823bd8SMatthew G Knepley 
5587f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5588f6dfbefdSBarry Smith 
5589420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
559031823bd8SMatthew G Knepley @*/
5591d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5592d71ae5a4SJacob Faibussowitsch {
559331823bd8SMatthew G Knepley   PetscFunctionBegin;
559431823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5595f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5596f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5597f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
55989566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5599f6dfbefdSBarry Smith   snes->npc = npc;
56003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
560131823bd8SMatthew G Knepley }
560231823bd8SMatthew G Knepley 
560331823bd8SMatthew G Knepley /*@
5604f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
560531823bd8SMatthew G Knepley 
5606f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
560731823bd8SMatthew G Knepley 
560831823bd8SMatthew G Knepley   Input Parameter:
5609f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
561031823bd8SMatthew G Knepley 
561131823bd8SMatthew G Knepley   Output Parameter:
5612e4094ef1SJacob Faibussowitsch . pc - preconditioner context
561331823bd8SMatthew G Knepley 
5614f6dfbefdSBarry Smith   Options Database Key:
5615f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5616b5badacbSBarry Smith 
5617dc4c0fb0SBarry Smith   Level: developer
5618dc4c0fb0SBarry Smith 
561995452b02SPatrick Sanan   Notes:
5620f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5621be95d8f1SBarry Smith 
5622f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5623f6dfbefdSBarry Smith   `SNES`
5624951fe5abSBarry Smith 
56251cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
562631823bd8SMatthew G Knepley @*/
5627d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5628d71ae5a4SJacob Faibussowitsch {
5629a64e098fSPeter Brune   const char *optionsprefix;
563031823bd8SMatthew G Knepley 
563131823bd8SMatthew G Knepley   PetscFunctionBegin;
563231823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56334f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5634efd4aadfSBarry Smith   if (!snes->npc) {
5635ec785e5bSStefano Zampini     void *ctx;
5636ec785e5bSStefano Zampini 
56379566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
56389566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
56399566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
56409566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
56419566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5642fb87a551SStefano Zampini     if (snes->ops->usercompute) {
5643fb87a551SStefano Zampini       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy));
5644fb87a551SStefano Zampini     } else {
5645ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5646ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5647fb87a551SStefano Zampini     }
56489566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
564931823bd8SMatthew G Knepley   }
5650efd4aadfSBarry Smith   *pc = snes->npc;
56513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
565231823bd8SMatthew G Knepley }
565331823bd8SMatthew G Knepley 
56543ad1a0b9SPatrick Farrell /*@
56553ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
56563ad1a0b9SPatrick Farrell 
56573ad1a0b9SPatrick Farrell   Not Collective
56583ad1a0b9SPatrick Farrell 
56593ad1a0b9SPatrick Farrell   Input Parameter:
5660f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
56613ad1a0b9SPatrick Farrell 
56623ad1a0b9SPatrick Farrell   Output Parameter:
5663420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
56643ad1a0b9SPatrick Farrell 
56653ad1a0b9SPatrick Farrell   Level: developer
56663ad1a0b9SPatrick Farrell 
56671cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
56683ad1a0b9SPatrick Farrell @*/
5669d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5670d71ae5a4SJacob Faibussowitsch {
56713ad1a0b9SPatrick Farrell   PetscFunctionBegin;
56723ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5673efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
56743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56753ad1a0b9SPatrick Farrell }
56763ad1a0b9SPatrick Farrell 
5677c40d0f55SPeter Brune /*@
5678420bcc1bSBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side.
5679c40d0f55SPeter Brune 
5680c3339decSBarry Smith   Logically Collective
5681c40d0f55SPeter Brune 
5682c40d0f55SPeter Brune   Input Parameter:
5683f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5684c40d0f55SPeter Brune 
5685c40d0f55SPeter Brune   Output Parameter:
5686c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5687c40d0f55SPeter Brune .vb
56882d547940SBarry Smith       PC_LEFT - left preconditioning
56892d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5690c40d0f55SPeter Brune .ve
5691c40d0f55SPeter Brune 
5692f6dfbefdSBarry Smith   Options Database Key:
569367b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5694c40d0f55SPeter Brune 
5695dc4c0fb0SBarry Smith   Level: intermediate
5696dc4c0fb0SBarry Smith 
5697f6dfbefdSBarry Smith   Note:
5698f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
56992d547940SBarry Smith 
5700420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5701c40d0f55SPeter Brune @*/
5702d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5703d71ae5a4SJacob Faibussowitsch {
5704c40d0f55SPeter Brune   PetscFunctionBegin;
5705c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5706c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5707b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
570854c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5709efd4aadfSBarry Smith   snes->npcside = side;
57103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5711c40d0f55SPeter Brune }
5712c40d0f55SPeter Brune 
5713c40d0f55SPeter Brune /*@
5714be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5715c40d0f55SPeter Brune 
5716c40d0f55SPeter Brune   Not Collective
5717c40d0f55SPeter Brune 
5718c40d0f55SPeter Brune   Input Parameter:
5719f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5720c40d0f55SPeter Brune 
5721c40d0f55SPeter Brune   Output Parameter:
5722c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5723c40d0f55SPeter Brune .vb
5724f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5725f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5726c40d0f55SPeter Brune .ve
5727c40d0f55SPeter Brune 
5728c40d0f55SPeter Brune   Level: intermediate
5729c40d0f55SPeter Brune 
5730420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5731c40d0f55SPeter Brune @*/
5732d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5733d71ae5a4SJacob Faibussowitsch {
5734c40d0f55SPeter Brune   PetscFunctionBegin;
5735c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57364f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5737efd4aadfSBarry Smith   *side = snes->npcside;
57383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5739c40d0f55SPeter Brune }
5740c40d0f55SPeter Brune 
57419e764e56SPeter Brune /*@
5742420bcc1bSBarry Smith   SNESSetLineSearch - Sets the linesearch to be used for `SNES`
57439e764e56SPeter Brune 
5744c3339decSBarry Smith   Collective
57459e764e56SPeter Brune 
57469e764e56SPeter Brune   Input Parameters:
5747f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
57489e764e56SPeter Brune - linesearch - the linesearch object
57499e764e56SPeter Brune 
5750dc4c0fb0SBarry Smith   Level: developer
5751dc4c0fb0SBarry Smith 
5752f6dfbefdSBarry Smith   Note:
5753420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
57549e764e56SPeter Brune   to configure it using the API).
57559e764e56SPeter Brune 
5756420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
57579e764e56SPeter Brune @*/
5758d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5759d71ae5a4SJacob Faibussowitsch {
57609e764e56SPeter Brune   PetscFunctionBegin;
57619e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5762f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
57639e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
57649566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
57659566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5766f5af7f23SKarl Rupp 
57679e764e56SPeter Brune   snes->linesearch = linesearch;
57683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57699e764e56SPeter Brune }
57709e764e56SPeter Brune 
5771a34ceb2aSJed Brown /*@
5772420bcc1bSBarry Smith   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5773f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
57749e764e56SPeter Brune 
57759e764e56SPeter Brune   Not Collective
57769e764e56SPeter Brune 
57779e764e56SPeter Brune   Input Parameter:
5778f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57799e764e56SPeter Brune 
57809e764e56SPeter Brune   Output Parameter:
57819e764e56SPeter Brune . linesearch - linesearch context
57829e764e56SPeter Brune 
5783162e0bf5SPeter Brune   Level: beginner
57849e764e56SPeter Brune 
57851cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
57869e764e56SPeter Brune @*/
5787d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5788d71ae5a4SJacob Faibussowitsch {
57899e764e56SPeter Brune   const char *optionsprefix;
57909e764e56SPeter Brune 
57919e764e56SPeter Brune   PetscFunctionBegin;
57929e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57934f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
57949e764e56SPeter Brune   if (!snes->linesearch) {
57959566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57969566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
57979566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
57989566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
57999566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
58009e764e56SPeter Brune   }
58019e764e56SPeter Brune   *linesearch = snes->linesearch;
58023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58039e764e56SPeter Brune }
5804