xref: /petsc/src/snes/interface/snes.c (revision 49abdd8a111d9c2ef7fc48ade253ef64e07f9b37)
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;
1397276fddSZach Atkins PetscLogEvent SNES_Solve, SNES_SetUp, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NewtonALEval, 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 
274ffeef943SBarry 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 
324ffeef943SBarry 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 
348ffeef943SBarry 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     }
41977e5a1f9SBarry Smith     if (snes->max_funcs == PETSC_UNLIMITED) {
42077e5a1f9SBarry Smith       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=unlimited\n", snes->max_its));
42177e5a1f9SBarry Smith     } else {
42263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum iterations=%" PetscInt_FMT ", maximum function evaluations=%" PetscInt_FMT "\n", snes->max_its, snes->max_funcs));
42377e5a1f9SBarry Smith     }
4249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  tolerances: relative=%g, absolute=%g, solution=%g\n", (double)snes->rtol, (double)snes->abstol, (double)snes->stol));
42548a46eb9SPierre Jolivet     if (snes->usesksp) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of linear solver iterations=%" PetscInt_FMT "\n", snes->linear_its));
42663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of function evaluations=%" PetscInt_FMT "\n", snes->nfuncs));
4279566063dSJacob Faibussowitsch     PetscCall(SNESGetNormSchedule(snes, &normschedule));
4289566063dSJacob Faibussowitsch     if (normschedule > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "  norm schedule %s\n", SNESNormSchedules[normschedule]));
42948a46eb9SPierre Jolivet     if (snes->gridsequence) PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of grid sequence refinements=%" PetscInt_FMT "\n", snes->gridsequence));
4309b94acceSBarry Smith     if (snes->ksp_ewconv) {
431fa9f3622SBarry Smith       kctx = (SNESKSPEW *)snes->kspconvctx;
4329b94acceSBarry Smith       if (kctx) {
43363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Eisenstat-Walker computation of KSP relative tolerance (version %" PetscInt_FMT ")\n", kctx->version));
4349566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    rtol_0=%g, rtol_max=%g, threshold=%g\n", (double)kctx->rtol_0, (double)kctx->rtol_max, (double)kctx->threshold));
4359566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    gamma=%g, alpha=%g, alpha2=%g\n", (double)kctx->gamma, (double)kctx->alpha, (double)kctx->alpha2));
4369b94acceSBarry Smith       }
4379b94acceSBarry Smith     }
438eb1f6c34SBarry Smith     if (snes->lagpreconditioner == -1) {
4399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is never rebuilt\n"));
440eb1f6c34SBarry Smith     } else if (snes->lagpreconditioner > 1) {
44163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Preconditioned is rebuilt every %" PetscInt_FMT " new Jacobians\n", snes->lagpreconditioner));
442eb1f6c34SBarry Smith     }
443eb1f6c34SBarry Smith     if (snes->lagjacobian == -1) {
4449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is never rebuilt\n"));
445eb1f6c34SBarry Smith     } else if (snes->lagjacobian > 1) {
44663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is rebuilt every %" PetscInt_FMT " SNES iterations\n", snes->lagjacobian));
447eb1f6c34SBarry Smith     }
4489566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4499566063dSJacob Faibussowitsch     PetscCall(DMSNESGetJacobian(dm, &cJ, &ctx));
450789d8953SBarry Smith     if (snes->mf_operator) {
4519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing\n"));
452789d8953SBarry Smith       pre = "Preconditioning ";
453789d8953SBarry Smith     }
4548404b7f3SBarry Smith     if (cJ == SNESComputeJacobianDefault) {
4559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences one column at a time\n", pre));
4568404b7f3SBarry Smith     } else if (cJ == SNESComputeJacobianDefaultColor) {
4579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using finite differences with coloring\n", pre));
458789d8953SBarry Smith       /* it slightly breaks data encapsulation for access the DMDA information directly */
459789d8953SBarry Smith     } else if (cJ == SNESComputeJacobian_DMDA) {
460789d8953SBarry Smith       MatFDColoring fdcoloring;
4619566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)dm, "DMDASNES_FDCOLORING", (PetscObject *)&fdcoloring));
462789d8953SBarry Smith       if (fdcoloring) {
4639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using colored finite differences on a DMDA\n", pre));
464789d8953SBarry Smith       } else {
4659566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  %sJacobian is built using a DMDA local Jacobian\n", pre));
466789d8953SBarry Smith       }
467996e1cbcSBarry Smith     } else if (snes->mf && !snes->mf_operator) {
4689566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Jacobian is applied matrix-free with differencing, no explicit Jacobian\n"));
4698404b7f3SBarry Smith     }
4700f5bd95cSBarry Smith   } else if (isstring) {
471317d6ea6SBarry Smith     const char *type;
4729566063dSJacob Faibussowitsch     PetscCall(SNESGetType(snes, &type));
4739566063dSJacob Faibussowitsch     PetscCall(PetscViewerStringSPrintf(viewer, " SNESType: %-7.7s", type));
474dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
47555849f57SBarry Smith   } else if (isbinary) {
47655849f57SBarry Smith     PetscInt    classid = SNES_FILE_CLASSID;
47755849f57SBarry Smith     MPI_Comm    comm;
47855849f57SBarry Smith     PetscMPIInt rank;
47955849f57SBarry Smith     char        type[256];
48055849f57SBarry Smith 
4819566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
4829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
483dd400576SPatrick Sanan     if (rank == 0) {
4849566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
4859566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(type, ((PetscObject)snes)->type_name, sizeof(type)));
4869566063dSJacob Faibussowitsch       PetscCall(PetscViewerBinaryWrite(viewer, type, sizeof(type), PETSC_CHAR));
48755849f57SBarry Smith     }
488dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
48972a02f06SBarry Smith   } else if (isdraw) {
49072a02f06SBarry Smith     PetscDraw draw;
49172a02f06SBarry Smith     char      str[36];
49289fd9fafSBarry Smith     PetscReal x, y, bottom, h;
49372a02f06SBarry Smith 
4949566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4959566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y));
4969566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(str, "SNES: ", sizeof(str)));
4979566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(str, ((PetscObject)snes)->type_name, sizeof(str)));
4989566063dSJacob Faibussowitsch     PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLUE, PETSC_DRAW_BLACK, str, NULL, &h));
49989fd9fafSBarry Smith     bottom = y - h;
5009566063dSJacob Faibussowitsch     PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom));
501dbbe0bcdSBarry Smith     PetscTryTypeMethod(snes, view, viewer);
502e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
503536b137fSBarry Smith   } else if (issaws) {
504d45a07a7SBarry Smith     PetscMPIInt rank;
5052657e9d9SBarry Smith     const char *name;
506d45a07a7SBarry Smith 
5079566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)snes, &name));
5089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
509dd400576SPatrick Sanan     if (!((PetscObject)snes)->amsmem && rank == 0) {
510d45a07a7SBarry Smith       char dir[1024];
511d45a07a7SBarry Smith 
5129566063dSJacob Faibussowitsch       PetscCall(PetscObjectViewSAWs((PetscObject)snes, viewer));
5139566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/its", name));
514792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, &snes->iter, 1, SAWs_READ, SAWs_INT));
51548a46eb9SPierre Jolivet       if (!snes->conv_hist) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, PETSC_DECIDE, PETSC_TRUE));
5169566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/conv_hist", name));
517792fecdfSBarry Smith       PetscCallSAWs(SAWs_Register, (dir, snes->conv_hist, 10, SAWs_READ, SAWs_DOUBLE));
518f05ece33SBarry Smith     }
519bfb97211SBarry Smith #endif
52072a02f06SBarry Smith   }
52172a02f06SBarry Smith   if (snes->linesearch) {
5229566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &linesearch));
5239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5249566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchView(linesearch, viewer));
5259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
52619bcc07fSBarry Smith   }
527efd4aadfSBarry Smith   if (snes->npc && snes->usesnpc) {
5289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5299566063dSJacob Faibussowitsch     PetscCall(SNESView(snes->npc, viewer));
5309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5314a0c5b0cSMatthew G Knepley   }
5329566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
5339566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(snes->dm, &dmsnes));
5349566063dSJacob Faibussowitsch   PetscCall(DMSNESView(dmsnes, viewer));
5359566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
5362c155ee1SBarry Smith   if (snes->usesksp) {
5379566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
5389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
5399566063dSJacob Faibussowitsch     PetscCall(KSPView(ksp, viewer));
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
5412c155ee1SBarry Smith   }
54272a02f06SBarry Smith   if (isdraw) {
54372a02f06SBarry Smith     PetscDraw draw;
5449566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
5459566063dSJacob Faibussowitsch     PetscCall(PetscDrawPopCurrentPoint(draw));
5467f1410a3SPeter Brune   }
5473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5489b94acceSBarry Smith }
5499b94acceSBarry Smith 
55076b2cf59SMatthew Knepley /*
55176b2cf59SMatthew Knepley   We retain a list of functions that also take SNES command
55276b2cf59SMatthew Knepley   line options. These are called at the end SNESSetFromOptions()
55376b2cf59SMatthew Knepley */
55476b2cf59SMatthew Knepley #define MAXSETFROMOPTIONS 5
555a7cc72afSBarry Smith static PetscInt numberofsetfromoptions;
5566849ba73SBarry Smith static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES);
55776b2cf59SMatthew Knepley 
558ac226902SBarry Smith /*@C
559f6dfbefdSBarry Smith   SNESAddOptionsChecker - Adds an additional function to check for `SNES` options.
56076b2cf59SMatthew Knepley 
56176b2cf59SMatthew Knepley   Not Collective
56276b2cf59SMatthew Knepley 
56376b2cf59SMatthew Knepley   Input Parameter:
56476b2cf59SMatthew Knepley . snescheck - function that checks for options
56576b2cf59SMatthew Knepley 
566420bcc1bSBarry Smith   Calling sequence of `snescheck`:
567420bcc1bSBarry Smith . snes - the `SNES` object for which it is checking options
568420bcc1bSBarry Smith 
56976b2cf59SMatthew Knepley   Level: developer
57076b2cf59SMatthew Knepley 
5711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`
57276b2cf59SMatthew Knepley @*/
573420bcc1bSBarry Smith PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES snes))
574d71ae5a4SJacob Faibussowitsch {
57576b2cf59SMatthew Knepley   PetscFunctionBegin;
57663a3b9bcSJacob Faibussowitsch   PetscCheck(numberofsetfromoptions < MAXSETFROMOPTIONS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %d allowed", MAXSETFROMOPTIONS);
57776b2cf59SMatthew Knepley   othersetfromoptions[numberofsetfromoptions++] = snescheck;
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57976b2cf59SMatthew Knepley }
58076b2cf59SMatthew Knepley 
581d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version)
582d71ae5a4SJacob Faibussowitsch {
583aa3661deSLisandro Dalcin   Mat          J;
584895c21f2SBarry Smith   MatNullSpace nullsp;
585aa3661deSLisandro Dalcin 
586aa3661deSLisandro Dalcin   PetscFunctionBegin;
5870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
588aa3661deSLisandro Dalcin 
58998613b67SLisandro Dalcin   if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) {
59098613b67SLisandro Dalcin     Mat A = snes->jacobian, B = snes->jacobian_pre;
5919566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(A ? A : B, NULL, &snes->vec_func));
59298613b67SLisandro Dalcin   }
59398613b67SLisandro Dalcin 
5940fdf79fbSJacob Faibussowitsch   PetscCheck(version == 1 || version == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator routines, only version 1 and 2");
595aa3661deSLisandro Dalcin   if (version == 1) {
5969566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
5979566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
5989566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
5991e2ae407SBarry Smith     /* TODO: the version 2 code should be merged into the MatCreateSNESMF() and MatCreateMFFD() infrastructure and then removed */
6000fdf79fbSJacob Faibussowitsch   } else /* if (version == 2) */ {
6015f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "SNESSetFunction() must be called first");
602570b7f6dSBarry Smith #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16)
603f6dfbefdSBarry Smith     PetscCall(MatCreateSNESMFMore(snes, snes->vec_func, &J));
604aa3661deSLisandro Dalcin #else
6052479783cSJose E. Roman     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "matrix-free operator routines (version 2)");
606aa3661deSLisandro Dalcin #endif
6070fdf79fbSJacob Faibussowitsch   }
608aa3661deSLisandro Dalcin 
60901c1178eSBarry Smith   /* attach any user provided null space that was on Amat to the newly created matrix-free matrix */
610895c21f2SBarry Smith   if (snes->jacobian) {
6119566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(snes->jacobian, &nullsp));
6121baa6e33SBarry Smith     if (nullsp) PetscCall(MatSetNullSpace(J, nullsp));
613895c21f2SBarry Smith   }
614895c21f2SBarry Smith 
61563a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "Setting default matrix-free operator routines (version %" PetscInt_FMT ")\n", version));
616d3462f78SMatthew Knepley   if (hasOperator) {
617aa3661deSLisandro Dalcin     /* This version replaces the user provided Jacobian matrix with a
618aa3661deSLisandro Dalcin        matrix-free version but still employs the user-provided preconditioner matrix. */
6199566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
620aa3661deSLisandro Dalcin   } else {
621aa3661deSLisandro Dalcin     /* This version replaces both the user-provided Jacobian and the user-
62201c1178eSBarry Smith      provided preconditioner Jacobian with the default matrix-free version. */
623b552625fSStefano Zampini     if (snes->npcside == PC_LEFT && snes->npc) {
6249566063dSJacob Faibussowitsch       if (!snes->jacobian) PetscCall(SNESSetJacobian(snes, J, NULL, NULL, NULL));
625172a4300SPeter Brune     } else {
626789d8953SBarry Smith       KSP       ksp;
627789d8953SBarry Smith       PC        pc;
628789d8953SBarry Smith       PetscBool match;
629789d8953SBarry Smith 
6309566063dSJacob Faibussowitsch       PetscCall(SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL));
631aa3661deSLisandro Dalcin       /* Force no preconditioner */
6329566063dSJacob Faibussowitsch       PetscCall(SNESGetKSP(snes, &ksp));
6339566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksp, &pc));
6342698c518SLisandro Dalcin       PetscCall(PetscObjectTypeCompareAny((PetscObject)pc, &match, PCSHELL, PCH2OPUS, ""));
635aa3661deSLisandro Dalcin       if (!match) {
6369566063dSJacob Faibussowitsch         PetscCall(PetscInfo(snes, "Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n"));
6379566063dSJacob Faibussowitsch         PetscCall(PCSetType(pc, PCNONE));
638aa3661deSLisandro Dalcin       }
639aa3661deSLisandro Dalcin     }
640789d8953SBarry Smith   }
6419566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&J));
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
643aa3661deSLisandro Dalcin }
644aa3661deSLisandro Dalcin 
645d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine, Mat Restrict, Vec Rscale, Mat Inject, DM dmcoarse, void *ctx)
646d71ae5a4SJacob Faibussowitsch {
647dfe15315SJed Brown   SNES snes = (SNES)ctx;
6480298fd71SBarry Smith   Vec  Xfine, Xfine_named = NULL, Xcoarse;
649dfe15315SJed Brown 
650dfe15315SJed Brown   PetscFunctionBegin;
65116ebb321SJed Brown   if (PetscLogPrintInfo) {
65216ebb321SJed Brown     PetscInt finelevel, coarselevel, fineclevel, coarseclevel;
6539566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmfine, &finelevel));
6549566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmfine, &fineclevel));
6559566063dSJacob Faibussowitsch     PetscCall(DMGetRefineLevel(dmcoarse, &coarselevel));
6569566063dSJacob Faibussowitsch     PetscCall(DMGetCoarsenLevel(dmcoarse, &coarseclevel));
65763a3b9bcSJacob 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));
65816ebb321SJed Brown   }
659dfe15315SJed Brown   if (dmfine == snes->dm) Xfine = snes->vec_sol;
660dfe15315SJed Brown   else {
6619566063dSJacob Faibussowitsch     PetscCall(DMGetNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
662dfe15315SJed Brown     Xfine = Xfine_named;
663dfe15315SJed Brown   }
6649566063dSJacob Faibussowitsch   PetscCall(DMGetNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
665907f5c5aSLawrence Mitchell   if (Inject) {
6669566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Inject, Xfine, Xcoarse));
667907f5c5aSLawrence Mitchell   } else {
6689566063dSJacob Faibussowitsch     PetscCall(MatRestrict(Restrict, Xfine, Xcoarse));
6699566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(Xcoarse, Xcoarse, Rscale));
670907f5c5aSLawrence Mitchell   }
6719566063dSJacob Faibussowitsch   PetscCall(DMRestoreNamedGlobalVector(dmcoarse, "SNESVecSol", &Xcoarse));
6729566063dSJacob Faibussowitsch   if (Xfine_named) PetscCall(DMRestoreNamedGlobalVector(dmfine, "SNESVecSol", &Xfine_named));
6733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
674dfe15315SJed Brown }
675dfe15315SJed Brown 
676d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm, DM dmc, void *ctx)
677d71ae5a4SJacob Faibussowitsch {
67816ebb321SJed Brown   PetscFunctionBegin;
6799566063dSJacob Faibussowitsch   PetscCall(DMCoarsenHookAdd(dmc, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, ctx));
6803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68116ebb321SJed Brown }
68216ebb321SJed Brown 
683a6950cb2SJed Brown /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can
684a6950cb2SJed Brown  * safely call SNESGetDM() in their residual evaluation routine. */
685d71ae5a4SJacob Faibussowitsch static PetscErrorCode KSPComputeOperators_SNES(KSP ksp, Mat A, Mat B, void *ctx)
686d71ae5a4SJacob Faibussowitsch {
687caa4e7f2SJed Brown   SNES            snes = (SNES)ctx;
68897d931d1SStefano Zampini   DMSNES          sdm;
6890298fd71SBarry Smith   Vec             X, Xnamed = NULL;
690dfe15315SJed Brown   DM              dmsave;
6914e269d77SPeter Brune   void           *ctxsave;
6928434afd1SBarry Smith   SNESJacobianFn *jac = NULL;
693caa4e7f2SJed Brown 
694caa4e7f2SJed Brown   PetscFunctionBegin;
695dfe15315SJed Brown   dmsave = snes->dm;
6969566063dSJacob Faibussowitsch   PetscCall(KSPGetDM(ksp, &snes->dm));
697dfe15315SJed Brown   if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */
69897d931d1SStefano Zampini   else {
699309d62e6SStefano Zampini     PetscBool has;
700309d62e6SStefano Zampini 
70197d931d1SStefano Zampini     /* We are on a coarser level, this vec was initialized using a DM restrict hook */
702309d62e6SStefano Zampini     PetscCall(DMHasNamedGlobalVector(snes->dm, "SNESVecSol", &has));
703309d62e6SStefano Zampini     PetscCheck(has, PetscObjectComm((PetscObject)snes->dm), PETSC_ERR_PLIB, "Missing SNESVecSol");
70497d931d1SStefano Zampini     PetscCall(DMGetNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
705dfe15315SJed Brown     X = Xnamed;
7069566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, NULL, NULL, &jac, &ctxsave));
7074e269d77SPeter Brune     /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */
70848a46eb9SPierre Jolivet     if (jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, SNESComputeJacobianDefaultColor, NULL));
7094e269d77SPeter Brune   }
7104e269d77SPeter Brune 
7112b93b426SMatthew G. Knepley   /* Compute the operators */
71297d931d1SStefano Zampini   PetscCall(DMGetDMSNES(snes->dm, &sdm));
71397d931d1SStefano Zampini   if (Xnamed && sdm->ops->computefunction) {
71497d931d1SStefano Zampini     /* The SNES contract with the user is that ComputeFunction is always called before ComputeJacobian.
71597d931d1SStefano Zampini        We make sure of this here. Disable affine shift since it is for the finest level */
71697d931d1SStefano Zampini     Vec F, saverhs = snes->vec_rhs;
71797d931d1SStefano Zampini 
71897d931d1SStefano Zampini     snes->vec_rhs = NULL;
71997d931d1SStefano Zampini     PetscCall(DMGetGlobalVector(snes->dm, &F));
72097d931d1SStefano Zampini     PetscCall(SNESComputeFunction(snes, X, F));
72197d931d1SStefano Zampini     PetscCall(DMRestoreGlobalVector(snes->dm, &F));
72297d931d1SStefano Zampini     snes->vec_rhs = saverhs;
72397d931d1SStefano Zampini     snes->nfuncs--; /* Do not log coarser level evaluations */
72497d931d1SStefano Zampini   }
72597d931d1SStefano Zampini   /* Make sure KSP DM has the Jacobian computation routine */
72697d931d1SStefano Zampini   if (!sdm->ops->computejacobian) PetscCall(DMCopyDMSNES(dmsave, snes->dm));
7279566063dSJacob Faibussowitsch   PetscCall(SNESComputeJacobian(snes, X, A, B));
72897d931d1SStefano Zampini 
7292b93b426SMatthew G. Knepley   /* Put the previous context back */
73048a46eb9SPierre Jolivet   if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) PetscCall(SNESSetJacobian(snes, NULL, NULL, jac, ctxsave));
7314e269d77SPeter Brune 
7329566063dSJacob Faibussowitsch   if (Xnamed) PetscCall(DMRestoreNamedGlobalVector(snes->dm, "SNESVecSol", &Xnamed));
733dfe15315SJed Brown   snes->dm = dmsave;
7343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
735caa4e7f2SJed Brown }
736caa4e7f2SJed Brown 
7376cab3a1bSJed Brown /*@
738dc4c0fb0SBarry Smith   SNESSetUpMatrices - ensures that matrices are available for `SNES` Newton-like methods, this is called by `SNESSetUp_XXX()`
7396cab3a1bSJed Brown 
7406cab3a1bSJed Brown   Collective
7416cab3a1bSJed Brown 
7424165533cSJose E. Roman   Input Parameter:
74320f4b53cSBarry Smith . snes - `SNES` object to configure
7446cab3a1bSJed Brown 
7456cab3a1bSJed Brown   Level: developer
7466cab3a1bSJed Brown 
747dc4c0fb0SBarry Smith   Note:
748dc4c0fb0SBarry 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`
749dc4c0fb0SBarry Smith 
75073a84a35SBarry Smith   Developer Note:
75173a84a35SBarry Smith   The functionality of this routine overlaps in a confusing way with the functionality of `SNESSetUpMatrixFree_Private()` which is called by
75273a84a35SBarry Smith   `SNESSetUp()` but sometimes `SNESSetUpMatrices()` is called without `SNESSetUp()` being called. A refactorization to simplify the
75373a84a35SBarry Smith   logic that handles the matrix-free case is desirable.
75473a84a35SBarry Smith 
7551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUp()`
7566cab3a1bSJed Brown @*/
757d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUpMatrices(SNES snes)
758d71ae5a4SJacob Faibussowitsch {
7596cab3a1bSJed Brown   DM     dm;
760942e3340SBarry Smith   DMSNES sdm;
7616cab3a1bSJed Brown 
7626cab3a1bSJed Brown   PetscFunctionBegin;
7639566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
7649566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
76573a84a35SBarry Smith   if (!snes->jacobian && snes->mf && !snes->mf_operator && !snes->jacobian_pre) {
7666cab3a1bSJed Brown     Mat   J;
7676cab3a1bSJed Brown     void *functx;
7689566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7699566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7709566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7719566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
7729566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, J, NULL, NULL));
7739566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
774caa4e7f2SJed Brown   } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) {
7756cab3a1bSJed Brown     Mat J, B;
7769566063dSJacob Faibussowitsch     PetscCall(MatCreateSNESMF(snes, &J));
7779566063dSJacob Faibussowitsch     PetscCall(MatMFFDSetOptionsPrefix(J, ((PetscObject)snes)->prefix));
7789566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(J));
7799566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
78006f20277SJed Brown     /* sdm->computejacobian was already set to reach here */
7819566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J, B, NULL, NULL));
7829566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7839566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
784caa4e7f2SJed Brown   } else if (!snes->jacobian_pre) {
7851ba9b98eSMatthew G. Knepley     PetscDS   prob;
7866cab3a1bSJed Brown     Mat       J, B;
7871ba9b98eSMatthew G. Knepley     PetscBool hasPrec = PETSC_FALSE;
7881ba9b98eSMatthew G. Knepley 
7896cab3a1bSJed Brown     J = snes->jacobian;
7909566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dm, &prob));
7919566063dSJacob Faibussowitsch     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
7929566063dSJacob Faibussowitsch     if (J) PetscCall(PetscObjectReference((PetscObject)J));
7939566063dSJacob Faibussowitsch     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
7949566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(snes->dm, &B));
7959566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
7969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&J));
7979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
7986cab3a1bSJed Brown   }
799caa4e7f2SJed Brown   {
800caa4e7f2SJed Brown     KSP ksp;
8019566063dSJacob Faibussowitsch     PetscCall(SNESGetKSP(snes, &ksp));
8029566063dSJacob Faibussowitsch     PetscCall(KSPSetComputeOperators(ksp, KSPComputeOperators_SNES, snes));
8039566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookAdd(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
804caa4e7f2SJed Brown   }
8053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8066cab3a1bSJed Brown }
8076cab3a1bSJed Brown 
808d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESMonitorPauseFinal_Internal(SNES snes)
809d71ae5a4SJacob Faibussowitsch {
8105e7c47f3SMatthew G. Knepley   PetscInt i;
8115e7c47f3SMatthew G. Knepley 
8125e7c47f3SMatthew G. Knepley   PetscFunctionBegin;
8133ba16761SJacob Faibussowitsch   if (!snes->pauseFinal) PetscFunctionReturn(PETSC_SUCCESS);
8145e7c47f3SMatthew G. Knepley   for (i = 0; i < snes->numbermonitors; ++i) {
8155e7c47f3SMatthew G. Knepley     PetscViewerAndFormat *vf = (PetscViewerAndFormat *)snes->monitorcontext[i];
8165e7c47f3SMatthew G. Knepley     PetscDraw             draw;
8175e7c47f3SMatthew G. Knepley     PetscReal             lpause;
8185e7c47f3SMatthew G. Knepley 
8195e7c47f3SMatthew G. Knepley     if (!vf) continue;
8205e7c47f3SMatthew G. Knepley     if (vf->lg) {
8215e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->lg, PETSC_OBJECT)) continue;
8225e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->lg)->classid != PETSC_DRAWLG_CLASSID) continue;
8239566063dSJacob Faibussowitsch       PetscCall(PetscDrawLGGetDraw(vf->lg, &draw));
8249566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8259566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8269566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8279566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8285e7c47f3SMatthew G. Knepley     } else {
8295e7c47f3SMatthew G. Knepley       PetscBool isdraw;
8305e7c47f3SMatthew G. Knepley 
8315e7c47f3SMatthew G. Knepley       if (!PetscCheckPointer(vf->viewer, PETSC_OBJECT)) continue;
8325e7c47f3SMatthew G. Knepley       if (((PetscObject)vf->viewer)->classid != PETSC_VIEWER_CLASSID) continue;
8339566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &isdraw));
8345e7c47f3SMatthew G. Knepley       if (!isdraw) continue;
8359566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(vf->viewer, 0, &draw));
8369566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPause(draw, &lpause));
8379566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, -1.0));
8389566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
8399566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetPause(draw, lpause));
8405e7c47f3SMatthew G. Knepley     }
8415e7c47f3SMatthew G. Knepley   }
8423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8435e7c47f3SMatthew G. Knepley }
8445e7c47f3SMatthew G. Knepley 
845fde5950dSBarry Smith /*@C
846fde5950dSBarry Smith   SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
847fde5950dSBarry Smith 
848c3339decSBarry Smith   Collective
849fde5950dSBarry Smith 
850fde5950dSBarry Smith   Input Parameters:
851dc4c0fb0SBarry Smith + snes         - `SNES` object you wish to monitor
852fde5950dSBarry Smith . name         - the monitor type one is seeking
853fde5950dSBarry Smith . help         - message indicating what monitoring is done
854fde5950dSBarry Smith . manual       - manual page for the monitor
855*49abdd8aSBarry Smith . monitor      - the monitor function, this must use a `PetscViewerFormat` as its context
856f6dfbefdSBarry 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
857fde5950dSBarry Smith 
858420bcc1bSBarry Smith   Calling sequence of `monitor`:
859420bcc1bSBarry Smith + snes - the nonlinear solver context
860420bcc1bSBarry Smith . it   - the current iteration
861420bcc1bSBarry Smith . r    - the current function norm
862420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
863420bcc1bSBarry Smith 
864420bcc1bSBarry Smith   Calling sequence of `monitorsetup`:
865420bcc1bSBarry Smith + snes - the nonlinear solver context
866420bcc1bSBarry Smith - vf   - a `PetscViewerAndFormat` struct that contains the `PetscViewer` and `PetscViewerFormat` to use
867420bcc1bSBarry Smith 
868f6dfbefdSBarry Smith   Options Database Key:
869f6dfbefdSBarry Smith . -name - trigger the use of this monitor in `SNESSetFromOptions()`
870f6dfbefdSBarry Smith 
871f6dfbefdSBarry Smith   Level: advanced
872fde5950dSBarry Smith 
873648c30bcSBarry Smith .seealso: [](ch_snes), `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
874db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
875e4094ef1SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
876db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
877c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
878db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
879db781477SPatrick Sanan           `PetscOptionsFList()`, `PetscOptionsEList()`
880fde5950dSBarry Smith @*/
881420bcc1bSBarry 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))
882d71ae5a4SJacob Faibussowitsch {
883fde5950dSBarry Smith   PetscViewer       viewer;
884fde5950dSBarry Smith   PetscViewerFormat format;
885fde5950dSBarry Smith   PetscBool         flg;
886fde5950dSBarry Smith 
887fde5950dSBarry Smith   PetscFunctionBegin;
888648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, name, &viewer, &format, &flg));
889fde5950dSBarry Smith   if (flg) {
890d43b4f6eSBarry Smith     PetscViewerAndFormat *vf;
8919566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
892648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
8931baa6e33SBarry Smith     if (monitorsetup) PetscCall((*monitorsetup)(snes, vf));
894*49abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
895fde5950dSBarry Smith   }
8963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
897fde5950dSBarry Smith }
898fde5950dSBarry Smith 
899a4598233SStefano Zampini PetscErrorCode SNESEWSetFromOptions_Private(SNESKSPEW *kctx, PetscBool print_api, MPI_Comm comm, const char *prefix)
900d71ae5a4SJacob Faibussowitsch {
901a4598233SStefano Zampini   const char *api = print_api ? "SNESKSPSetParametersEW" : NULL;
902a4598233SStefano Zampini 
9030f0abf79SStefano Zampini   PetscFunctionBegin;
9040f0abf79SStefano Zampini   PetscOptionsBegin(comm, prefix, "Eisenstat and Walker type forcing options", "KSP");
905a4598233SStefano Zampini   PetscCall(PetscOptionsInt("-ksp_ew_version", "Version 1, 2 or 3", api, kctx->version, &kctx->version, NULL));
906a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtol0", "0 <= rtol0 < 1", api, kctx->rtol_0, &kctx->rtol_0, NULL));
907a4598233SStefano Zampini   kctx->rtol_max = PetscMax(kctx->rtol_0, kctx->rtol_max);
908a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_rtolmax", "0 <= rtolmax < 1", api, kctx->rtol_max, &kctx->rtol_max, NULL));
909a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_gamma", "0 <= gamma <= 1", api, kctx->gamma, &kctx->gamma, NULL));
910a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha", "1 < alpha <= 2", api, kctx->alpha, &kctx->alpha, NULL));
9110f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_alpha2", "alpha2", NULL, kctx->alpha2, &kctx->alpha2, NULL));
912a4598233SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_threshold", "0 < threshold < 1", api, kctx->threshold, &kctx->threshold, NULL));
9130f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p1", "p1", NULL, kctx->v4_p1, &kctx->v4_p1, NULL));
9140f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p2", "p2", NULL, kctx->v4_p2, &kctx->v4_p2, NULL));
9150f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_p3", "p3", NULL, kctx->v4_p3, &kctx->v4_p3, NULL));
9160f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m1", "Scaling when rk-1 in [p2,p3)", NULL, kctx->v4_m1, &kctx->v4_m1, NULL));
9170f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m2", "Scaling when rk-1 in [p3,+infty)", NULL, kctx->v4_m2, &kctx->v4_m2, NULL));
9180f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m3", "Threshold for successive rtol (0.1 in Eq.7)", NULL, kctx->v4_m3, &kctx->v4_m3, NULL));
9190f0abf79SStefano Zampini   PetscCall(PetscOptionsReal("-ksp_ew_v4_m4", "Adaptation scaling (0.5 in Eq.7)", NULL, kctx->v4_m4, &kctx->v4_m4, NULL));
9200f0abf79SStefano Zampini   PetscOptionsEnd();
9213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9220f0abf79SStefano Zampini }
9230f0abf79SStefano Zampini 
9249b94acceSBarry Smith /*@
925f6dfbefdSBarry Smith   SNESSetFromOptions - Sets various `SNES` and `KSP` parameters from user options.
9269b94acceSBarry Smith 
927c3339decSBarry Smith   Collective
928c7afd0dbSLois Curfman McInnes 
9299b94acceSBarry Smith   Input Parameter:
930f6dfbefdSBarry Smith . snes - the `SNES` context
9319b94acceSBarry Smith 
93236851e7fSLois Curfman McInnes   Options Database Keys:
933f6dfbefdSBarry Smith + -snes_type <type>                                                            - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, `SNESType` for complete list
934b39c3a46SLois Curfman McInnes . -snes_rtol <rtol>                                                            - relative decrease in tolerance norm from initial
93577e5a1f9SBarry Smith . -snes_atol <abstol>                                                          - absolute tolerance of residual norm
93677e5a1f9SBarry Smith . -snes_stol <stol>                                                            - convergence tolerance in terms of the norm of the change in the solution between steps
937e4d06f11SPatrick Farrell . -snes_divergence_tolerance <divtol>                                          - if the residual goes above divtol*rnorm0, exit with divergence
938b39c3a46SLois Curfman McInnes . -snes_max_it <max_it>                                                        - maximum number of iterations
939b39c3a46SLois Curfman McInnes . -snes_max_funcs <max_funcs>                                                  - maximum number of function evaluations
94077e5a1f9SBarry Smith . -snes_force_iteration <force>                                                - force `SNESSolve()` to take at least one iteration
9414839bfe8SBarry Smith . -snes_max_fail <max_fail>                                                    - maximum number of line search failures allowed before stopping, default is none
942ddf469c8SBarry Smith . -snes_max_linear_solve_fail                                                  - number of linear solver failures before SNESSolve() stops
943a8054027SBarry Smith . -snes_lag_preconditioner <lag>                                               - how often preconditioner is rebuilt (use -1 to never rebuild)
9443d5a8a6aSBarry Smith . -snes_lag_preconditioner_persists <true,false>                               - retains the -snes_lag_preconditioner information across multiple SNESSolve()
945e35cf81dSBarry Smith . -snes_lag_jacobian <lag>                                                     - how often Jacobian is rebuilt (use -1 to never rebuild)
9463d5a8a6aSBarry Smith . -snes_lag_jacobian_persists <true,false>                                     - retains the -snes_lag_jacobian information across multiple SNESSolve()
947ceaaa498SBarry 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.
948fde5950dSBarry Smith . -snes_monitor [ascii][:filename][:viewer format]                             - prints residual norm at each iteration. if no filename given prints to stdout
949fde5950dSBarry Smith . -snes_monitor_solution [ascii binary draw][:filename][:viewer format]        - plots solution at each iteration
950fde5950dSBarry Smith . -snes_monitor_residual [ascii binary draw][:filename][:viewer format]        - plots residual (not its norm) at each iteration
951fde5950dSBarry Smith . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration
9524619e776SBarry Smith . -snes_monitor_lg_residualnorm                                                - plots residual norm at each iteration
953459f5d12SBarry Smith . -snes_monitor_lg_range                                                       - plots residual norm at each iteration
9545e7c47f3SMatthew G. Knepley . -snes_monitor_pause_final                                                    - Pauses all monitor drawing after the solver ends
955e24b481bSBarry Smith . -snes_fd                                                                     - use finite differences to compute Jacobian; very slow, only for testing
956e2e60de9SPeter Brune . -snes_fd_color                                                               - use finite differences with coloring to compute Jacobian
957ceaaa498SBarry Smith . -snes_mf_ksp_monitor                                                         - if using matrix-free multiply then print h at each `KSP` iteration
958b5badacbSBarry Smith . -snes_converged_reason                                                       - print the reason for convergence/divergence after each solve
959ceaaa498SBarry Smith . -npc_snes_type <type>                                                        - the `SNES` type to use as a nonlinear preconditioner
960e62ac41dSBarry 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.
961e62ac41dSBarry 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.
96282738288SBarry Smith 
963f6dfbefdSBarry Smith   Options Database Keys for Eisenstat-Walker method:
964fa9f3622SBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
9654b27c08aSLois Curfman McInnes . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
96636851e7fSLois Curfman McInnes . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
96736851e7fSLois Curfman McInnes . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
96836851e7fSLois Curfman McInnes . -snes_ksp_ew_gamma <gamma>         - Sets gamma
96936851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha <alpha>         - Sets alpha
97036851e7fSLois Curfman McInnes . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
97136851e7fSLois Curfman McInnes - -snes_ksp_ew_threshold <threshold> - Sets threshold
97282738288SBarry Smith 
973dc4c0fb0SBarry Smith   Level: beginner
974dc4c0fb0SBarry Smith 
97511ca99fdSLois Curfman McInnes   Notes:
976ec5066bdSBarry Smith   To see all options, run your program with the -help option or consult the users manual
977ec5066bdSBarry Smith 
978420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
979420bcc1bSBarry Smith   and computing explicitly with
980f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
98183e2fdc7SBarry Smith 
982420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESType`, `SNESSetOptionsPrefix()`, `SNESResetFromOptions()`, `SNES`, `SNESCreate()`, `MatCreateSNESMF()`, `MatFDColoring`
9839b94acceSBarry Smith @*/
984d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFromOptions(SNES snes)
985d71ae5a4SJacob Faibussowitsch {
9868afaa268SBarry Smith   PetscBool   flg, pcset, persist, set;
98777e5a1f9SBarry Smith   PetscInt    i, indx, lag, grids, max_its, max_funcs;
98804d7464bSBarry Smith   const char *deft        = SNESNEWTONLS;
989649ef022SMatthew Knepley   const char *convtests[] = {"default", "skip", "correct_pressure"};
99085385478SLisandro Dalcin   SNESKSPEW  *kctx        = NULL;
9910f0abf79SStefano Zampini   char        type[256], monfilename[PETSC_MAX_PATH_LEN], ewprefix[256];
992c40d0f55SPeter Brune   PCSide      pcside;
993a64e098fSPeter Brune   const char *optionsprefix;
99477e5a1f9SBarry Smith   PetscReal   rtol, abstol, stol;
9959b94acceSBarry Smith 
9963a40ed3dSBarry Smith   PetscFunctionBegin;
9970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
9989566063dSJacob Faibussowitsch   PetscCall(SNESRegisterAll());
999d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
1000639ff905SBarry Smith   if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name;
10019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-snes_type", "Nonlinear solver method", "SNESSetType", SNESList, deft, type, 256, &flg));
1002d64ed03dSBarry Smith   if (flg) {
10039566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, type));
10047adad957SLisandro Dalcin   } else if (!((PetscObject)snes)->type_name) {
10059566063dSJacob Faibussowitsch     PetscCall(SNESSetType(snes, deft));
1006d64ed03dSBarry Smith   }
1007186905e3SBarry Smith 
100877e5a1f9SBarry Smith   abstol    = snes->abstol;
100977e5a1f9SBarry Smith   rtol      = snes->rtol;
101077e5a1f9SBarry Smith   stol      = snes->stol;
101177e5a1f9SBarry Smith   max_its   = snes->max_its;
101277e5a1f9SBarry Smith   max_funcs = snes->max_funcs;
101377e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_rtol", "Stop if decrease in function norm less than", "SNESSetTolerances", snes->rtol, &rtol, NULL));
101477e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_atol", "Stop if function norm less than", "SNESSetTolerances", snes->abstol, &abstol, NULL));
101577e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_stol", "Stop if step length less than", "SNESSetTolerances", snes->stol, &stol, NULL));
101677e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_it", "Maximum iterations", "SNESSetTolerances", snes->max_its, &max_its, NULL));
101777e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_funcs", "Maximum function evaluations", "SNESSetTolerances", snes->max_funcs, &max_funcs, NULL));
101877e5a1f9SBarry Smith   PetscCall(SNESSetTolerances(snes, abstol, rtol, stol, max_its, max_funcs));
101977e5a1f9SBarry Smith 
102077e5a1f9SBarry Smith   PetscCall(PetscOptionsReal("-snes_divergence_tolerance", "Stop if residual norm increases by this factor", "SNESSetDivergenceTolerance", snes->divtol, &snes->divtol, &flg));
102177e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetDivergenceTolerance(snes, snes->divtol));
102277e5a1f9SBarry Smith 
102377e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_fail", "Maximum nonlinear step failures", "SNESSetMaxNonlinearStepFailures", snes->maxFailures, &snes->maxFailures, &flg));
102477e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxNonlinearStepFailures(snes, snes->maxFailures));
102577e5a1f9SBarry Smith 
102677e5a1f9SBarry Smith   PetscCall(PetscOptionsInt("-snes_max_linear_solve_fail", "Maximum failures in linear solves allowed", "SNESSetMaxLinearSolveFailures", snes->maxLinearSolveFailures, &snes->maxLinearSolveFailures, &flg));
102777e5a1f9SBarry Smith   if (flg) PetscCall(SNESSetMaxLinearSolveFailures(snes, snes->maxLinearSolveFailures));
102877e5a1f9SBarry Smith 
10299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_error_if_not_converged", "Generate error if solver does not converge", "SNESSetErrorIfNotConverged", snes->errorifnotconverged, &snes->errorifnotconverged, NULL));
10309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_force_iteration", "Force SNESSolve() to take at least one iteration", "SNESSetForceIteration", snes->forceiteration, &snes->forceiteration, NULL));
10319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_check_jacobian_domain_error", "Check Jacobian domain error after Jacobian evaluation", "SNESCheckJacobianDomainError", snes->checkjacdomainerror, &snes->checkjacdomainerror, NULL));
103285385478SLisandro Dalcin 
10339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_preconditioner", "How often to rebuild preconditioner", "SNESSetLagPreconditioner", snes->lagpreconditioner, &lag, &flg));
1034a8054027SBarry Smith   if (flg) {
10355f80ce2aSJacob 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");
10369566063dSJacob Faibussowitsch     PetscCall(SNESSetLagPreconditioner(snes, lag));
1037a8054027SBarry Smith   }
10389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_preconditioner_persists", "Preconditioner lagging through multiple SNES solves", "SNESSetLagPreconditionerPersists", snes->lagjac_persist, &persist, &flg));
10391baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagPreconditionerPersists(snes, persist));
10409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_lag_jacobian", "How often to rebuild Jacobian", "SNESSetLagJacobian", snes->lagjacobian, &lag, &flg));
1041e35cf81dSBarry Smith   if (flg) {
10425f80ce2aSJacob 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");
10439566063dSJacob Faibussowitsch     PetscCall(SNESSetLagJacobian(snes, lag));
1044e35cf81dSBarry Smith   }
10459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_lag_jacobian_persists", "Jacobian lagging through multiple SNES solves", "SNESSetLagJacobianPersists", snes->lagjac_persist, &persist, &flg));
10461baa6e33SBarry Smith   if (flg) PetscCall(SNESSetLagJacobianPersists(snes, persist));
104737ec4e1aSPeter Brune 
10489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_grid_sequence", "Use grid sequencing to generate initial guess", "SNESSetGridSequence", snes->gridsequence, &grids, &flg));
10491baa6e33SBarry Smith   if (flg) PetscCall(SNESSetGridSequence(snes, grids));
1050a8054027SBarry Smith 
1051400f6f02SBarry Smith   PetscCall(PetscOptionsEList("-snes_convergence_test", "Convergence test", "SNESSetConvergenceTest", convtests, PETSC_STATIC_ARRAY_LENGTH(convtests), "default", &indx, &flg));
105285385478SLisandro Dalcin   if (flg) {
105385385478SLisandro Dalcin     switch (indx) {
1054d71ae5a4SJacob Faibussowitsch     case 0:
1055d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedDefault, NULL, NULL));
1056d71ae5a4SJacob Faibussowitsch       break;
1057d71ae5a4SJacob Faibussowitsch     case 1:
1058d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedSkip, NULL, NULL));
1059d71ae5a4SJacob Faibussowitsch       break;
1060d71ae5a4SJacob Faibussowitsch     case 2:
1061d71ae5a4SJacob Faibussowitsch       PetscCall(SNESSetConvergenceTest(snes, SNESConvergedCorrectPressure, NULL, NULL));
1062d71ae5a4SJacob Faibussowitsch       break;
106385385478SLisandro Dalcin     }
106485385478SLisandro Dalcin   }
106585385478SLisandro Dalcin 
10669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_norm_schedule", "SNES Norm schedule", "SNESSetNormSchedule", SNESNormSchedules, 5, "function", &indx, &flg));
10679566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNormSchedule(snes, (SNESNormSchedule)indx));
1068fdacfa88SPeter Brune 
10699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEList("-snes_function_type", "SNES Norm schedule", "SNESSetFunctionType", SNESFunctionTypes, 2, "unpreconditioned", &indx, &flg));
10709566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetFunctionType(snes, (SNESFunctionType)indx));
1071186905e3SBarry Smith 
107285385478SLisandro Dalcin   kctx = (SNESKSPEW *)snes->kspconvctx;
107385385478SLisandro Dalcin 
10749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_ksp_ew", "Use Eisentat-Walker linear system convergence test", "SNESKSPSetUseEW", snes->ksp_ewconv, &snes->ksp_ewconv, NULL));
1075186905e3SBarry Smith 
10760f0abf79SStefano Zampini   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
10770f0abf79SStefano Zampini   PetscCall(PetscSNPrintf(ewprefix, sizeof(ewprefix), "%s%s", optionsprefix ? optionsprefix : "", "snes_"));
1078a4598233SStefano Zampini   PetscCall(SNESEWSetFromOptions_Private(kctx, PETSC_TRUE, PetscObjectComm((PetscObject)snes), ewprefix));
1079186905e3SBarry Smith 
108090d69ab7SBarry Smith   flg = PETSC_FALSE;
10819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_cancel", "Remove all monitors", "SNESMonitorCancel", flg, &flg, &set));
10829566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESMonitorCancel(snes));
1083eabae89aSBarry Smith 
10849566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor", "Monitor norm of function", "SNESMonitorDefault", SNESMonitorDefault, SNESMonitorDefaultSetUp));
10859566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_short", "Monitor norm of function with fewer digits", "SNESMonitorDefaultShort", SNESMonitorDefaultShort, NULL));
10869566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_range", "Monitor range of elements of function", "SNESMonitorRange", SNESMonitorRange, NULL));
1087eabae89aSBarry Smith 
10889566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_ratio", "Monitor ratios of the norm of function for consecutive steps", "SNESMonitorRatio", SNESMonitorRatio, SNESMonitorRatioSetUp));
10899566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_field", "Monitor norm of function (split into fields)", "SNESMonitorDefaultField", SNESMonitorDefaultField, NULL));
10909566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution", "View solution at each iteration", "SNESMonitorSolution", SNESMonitorSolution, NULL));
10919566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_solution_update", "View correction at each iteration", "SNESMonitorSolutionUpdate", SNESMonitorSolutionUpdate, NULL));
10929566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_residual", "View residual at each iteration", "SNESMonitorResidual", SNESMonitorResidual, NULL));
10939566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_jacupdate_spectrum", "Print the change in the spectrum of the Jacobian", "SNESMonitorJacUpdateSpectrum", SNESMonitorJacUpdateSpectrum, NULL));
10949566063dSJacob Faibussowitsch   PetscCall(SNESMonitorSetFromOptions(snes, "-snes_monitor_fields", "Monitor norm of function per field", "SNESMonitorSet", SNESMonitorFields, NULL));
10959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_pause_final", "Pauses all draw monitors at the final iterate", "SNESMonitorPauseFinal_Internal", PETSC_FALSE, &snes->pauseFinal, NULL));
10962db13446SMatthew G. Knepley 
10979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-snes_monitor_python", "Use Python function", "SNESMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
10989566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)snes, monfilename));
10995180491cSLisandro Dalcin 
110090d69ab7SBarry Smith   flg = PETSC_FALSE;
11019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_lg_range", "Plot function range at each iteration", "SNESMonitorLGRange", flg, &flg, NULL));
1102459f5d12SBarry Smith   if (flg) {
1103459f5d12SBarry Smith     PetscViewer ctx;
1104e24b481bSBarry Smith 
11059566063dSJacob Faibussowitsch     PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
1106*49abdd8aSBarry Smith     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscCtxDestroyFn *)PetscViewerDestroy));
1107459f5d12SBarry Smith   }
11082e7541e6SPeter Brune 
1109648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
1110648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_converged_reason", &snes->convergedreasonviewer, &snes->convergedreasonformat, NULL));
111190d69ab7SBarry Smith   flg = PETSC_FALSE;
11129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_converged_reason_view_cancel", "Remove all converged reason viewers", "SNESConvergedReasonViewCancel", flg, &flg, &set));
11139566063dSJacob Faibussowitsch   if (set && flg) PetscCall(SNESConvergedReasonViewCancel(snes));
1114c4421ceaSFande Kong 
1115c4421ceaSFande Kong   flg = PETSC_FALSE;
11169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd", "Use finite differences (slow) to compute Jacobian", "SNESComputeJacobianDefault", flg, &flg, NULL));
11174b27c08aSLois Curfman McInnes   if (flg) {
11186cab3a1bSJed Brown     void *functx;
1119b1f624c7SBarry Smith     DM    dm;
11209566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1121800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11229566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
11239566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefault, functx));
11249566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference Jacobian matrix\n"));
11259b94acceSBarry Smith   }
1126639f9d9dSBarry Smith 
112744848bc4SPeter Brune   flg = PETSC_FALSE;
11289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_function", "Use finite differences (slow) to compute function from user objective", "SNESObjectiveComputeFunctionDefaultFD", flg, &flg, NULL));
11291baa6e33SBarry Smith   if (flg) PetscCall(SNESSetFunction(snes, NULL, SNESObjectiveComputeFunctionDefaultFD, NULL));
113097584545SPeter Brune 
113197584545SPeter Brune   flg = PETSC_FALSE;
11329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_fd_color", "Use finite differences with coloring to compute Jacobian", "SNESComputeJacobianDefaultColor", flg, &flg, NULL));
113344848bc4SPeter Brune   if (flg) {
1134c52e227fSPeter Brune     DM dm;
11359566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
1136800f99ffSJeremy L Thompson     PetscCall(DMSNESUnsetJacobianContext_Internal(dm));
11379566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes, snes->jacobian, snes->jacobian_pre, SNESComputeJacobianDefaultColor, NULL));
11389566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Setting default finite difference coloring Jacobian matrix\n"));
113944848bc4SPeter Brune   }
114044848bc4SPeter Brune 
1141aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf_operator", "Use a Matrix-Free Jacobian with user-provided preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf_operator, &flg));
1143d8f46077SPeter Brune   if (flg && snes->mf_operator) {
1144a8248277SBarry Smith     snes->mf_operator = PETSC_TRUE;
1145d8f46077SPeter Brune     snes->mf          = PETSC_TRUE;
1146a8248277SBarry Smith   }
1147aa3661deSLisandro Dalcin   flg = PETSC_FALSE;
11489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_mf", "Use a Matrix-Free Jacobian with no preconditioner matrix", "SNESSetUseMatrixFree", PETSC_FALSE, &snes->mf, &flg));
1149d8f46077SPeter Brune   if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE;
11509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-snes_mf_version", "Matrix-Free routines version 1 or 2", "None", snes->mf_version, &snes->mf_version, NULL));
1151d28543b3SPeter Brune 
1152c40d0f55SPeter Brune   flg = PETSC_FALSE;
11539566063dSJacob Faibussowitsch   PetscCall(SNESGetNPCSide(snes, &pcside));
11549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-snes_npc_side", "SNES nonlinear preconditioner side", "SNESSetNPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
11559566063dSJacob Faibussowitsch   if (flg) PetscCall(SNESSetNPCSide(snes, pcside));
1156c40d0f55SPeter Brune 
1157e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
11588a70d858SHong Zhang   /*
11598a70d858SHong Zhang     Publish convergence information using SAWs
11608a70d858SHong Zhang   */
11618a70d858SHong Zhang   flg = PETSC_FALSE;
11629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-snes_monitor_saws", "Publish SNES progress using SAWs", "SNESMonitorSet", flg, &flg, NULL));
11638a70d858SHong Zhang   if (flg) {
11648a70d858SHong Zhang     void *ctx;
11659566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSAWsCreate(snes, &ctx));
11669566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorSAWs, ctx, SNESMonitorSAWsDestroy));
11678a70d858SHong Zhang   }
11688a70d858SHong Zhang #endif
11698a70d858SHong Zhang #if defined(PETSC_HAVE_SAWS)
1170b90c6cbeSBarry Smith   {
1171b90c6cbeSBarry Smith     PetscBool set;
1172b90c6cbeSBarry Smith     flg = PETSC_FALSE;
11739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-snes_saws_block", "Block for SAWs at end of SNESSolve", "PetscObjectSAWsBlock", ((PetscObject)snes)->amspublishblock, &flg, &set));
11741baa6e33SBarry Smith     if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)snes, flg));
1175b90c6cbeSBarry Smith   }
1176b90c6cbeSBarry Smith #endif
1177b90c6cbeSBarry Smith 
117848a46eb9SPierre Jolivet   for (i = 0; i < numberofsetfromoptions; i++) PetscCall((*othersetfromoptions[i])(snes));
117976b2cf59SMatthew Knepley 
1180dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setfromoptions, PetscOptionsObject);
11815d973c19SBarry Smith 
11825d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
1183dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)snes, PetscOptionsObject));
1184d0609cedSBarry Smith   PetscOptionsEnd();
11854bbc92c1SBarry Smith 
1186d8d34be6SBarry Smith   if (snes->linesearch) {
11879566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
11889566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFromOptions(snes->linesearch));
1189d8d34be6SBarry Smith   }
11909e764e56SPeter Brune 
11916aa5e7e9SBarry Smith   if (snes->usesksp) {
11929566063dSJacob Faibussowitsch     if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
11939566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(snes->ksp, snes->jacobian, snes->jacobian_pre));
11949566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(snes->ksp));
11956aa5e7e9SBarry Smith   }
11966991f827SBarry Smith 
1197b5badacbSBarry Smith   /* if user has set the SNES NPC type via options database, create it. */
11989566063dSJacob Faibussowitsch   PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
11999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)snes)->options, optionsprefix, "-npc_snes_type", &pcset));
120048a46eb9SPierre Jolivet   if (pcset && (!snes->npc)) PetscCall(SNESGetNPC(snes, &snes->npc));
12011baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESSetFromOptions(snes->npc));
1202b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled++;
12033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1204b3cd9a81SMatthew G. Knepley }
1205b3cd9a81SMatthew G. Knepley 
1206b3cd9a81SMatthew G. Knepley /*@
1207420bcc1bSBarry Smith   SNESResetFromOptions - Sets various `SNES` and `KSP` parameters from user options ONLY if the `SNESSetFromOptions()` was previously called
1208b3cd9a81SMatthew G. Knepley 
1209c3339decSBarry Smith   Collective
1210b3cd9a81SMatthew G. Knepley 
1211b3cd9a81SMatthew G. Knepley   Input Parameter:
1212f6dfbefdSBarry Smith . snes - the `SNES` context
1213b3cd9a81SMatthew G. Knepley 
1214420bcc1bSBarry Smith   Level: advanced
1215b3cd9a81SMatthew G. Knepley 
12161cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESSetOptionsPrefix()`
1217b3cd9a81SMatthew G. Knepley @*/
1218d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESResetFromOptions(SNES snes)
1219d71ae5a4SJacob Faibussowitsch {
1220b3cd9a81SMatthew G. Knepley   PetscFunctionBegin;
12219566063dSJacob Faibussowitsch   if (snes->setfromoptionscalled) PetscCall(SNESSetFromOptions(snes));
12223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12239b94acceSBarry Smith }
12249b94acceSBarry Smith 
1225bb9467b5SJed Brown /*@C
1226d25893d9SBarry Smith   SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for
1227d25893d9SBarry Smith   the nonlinear solvers.
1228d25893d9SBarry Smith 
1229dc4c0fb0SBarry Smith   Logically Collective; No Fortran Support
1230d25893d9SBarry Smith 
1231d25893d9SBarry Smith   Input Parameters:
1232f6dfbefdSBarry Smith + snes    - the `SNES` context
1233d25893d9SBarry Smith . compute - function to compute the context
1234*49abdd8aSBarry Smith - destroy - function to destroy the context, see `PetscCtxDestroyFn` for the calling sequence
1235d25893d9SBarry Smith 
1236420bcc1bSBarry Smith   Calling sequence of `compute`:
1237420bcc1bSBarry Smith + snes - the `SNES` context
1238420bcc1bSBarry Smith - ctx  - context to be computed
1239420bcc1bSBarry Smith 
1240d25893d9SBarry Smith   Level: intermediate
1241d25893d9SBarry Smith 
1242f6dfbefdSBarry Smith   Note:
1243f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1244f6dfbefdSBarry Smith 
1245f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1246f6dfbefdSBarry Smith 
1247*49abdd8aSBarry Smith .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`, `PetscCtxDestroyFn`
1248d25893d9SBarry Smith @*/
1249*49abdd8aSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscCtxDestroyFn *destroy)
1250d71ae5a4SJacob Faibussowitsch {
1251d25893d9SBarry Smith   PetscFunctionBegin;
1252d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1253d25893d9SBarry Smith   snes->ops->usercompute = compute;
1254*49abdd8aSBarry Smith   snes->ops->ctxdestroy  = destroy;
12553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1256d25893d9SBarry Smith }
1257a847f771SSatish Balay 
1258b07ff414SBarry Smith /*@
1259f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12609b94acceSBarry Smith 
1261c3339decSBarry Smith   Logically Collective
1262fee21e36SBarry Smith 
1263c7afd0dbSLois Curfman McInnes   Input Parameters:
1264f6dfbefdSBarry Smith + snes - the `SNES` context
1265*49abdd8aSBarry Smith - ctx  - optional user context
1266c7afd0dbSLois Curfman McInnes 
126736851e7fSLois Curfman McInnes   Level: intermediate
126836851e7fSLois Curfman McInnes 
1269f6dfbefdSBarry Smith   Notes:
1270f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1271f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1272f6dfbefdSBarry Smith 
1273f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1274f6dfbefdSBarry Smith 
1275420bcc1bSBarry Smith   Fortran Note:
1276dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1277420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1278daf670e6SBarry Smith 
12791cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12809b94acceSBarry Smith @*/
1281*49abdd8aSBarry Smith PetscErrorCode SNESSetApplicationContext(SNES snes, void *ctx)
1282d71ae5a4SJacob Faibussowitsch {
1283b07ff414SBarry Smith   KSP ksp;
12841b2093e4SBarry Smith 
12853a40ed3dSBarry Smith   PetscFunctionBegin;
12860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12879566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
1288*49abdd8aSBarry Smith   PetscCall(KSPSetApplicationContext(ksp, ctx));
1289*49abdd8aSBarry Smith   snes->ctx = ctx;
12903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12919b94acceSBarry Smith }
129274679c65SBarry Smith 
1293b07ff414SBarry Smith /*@
12949b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1295420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12969b94acceSBarry Smith 
1297c7afd0dbSLois Curfman McInnes   Not Collective
1298c7afd0dbSLois Curfman McInnes 
12999b94acceSBarry Smith   Input Parameter:
1300f6dfbefdSBarry Smith . snes - `SNES` context
13019b94acceSBarry Smith 
13029b94acceSBarry Smith   Output Parameter:
1303*49abdd8aSBarry Smith . ctx - user context
13049b94acceSBarry Smith 
130536851e7fSLois Curfman McInnes   Level: intermediate
130636851e7fSLois Curfman McInnes 
1307420bcc1bSBarry Smith   Fortran Note:
1308dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1309420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1310dc4c0fb0SBarry Smith 
1311420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13129b94acceSBarry Smith @*/
1313*49abdd8aSBarry Smith PetscErrorCode SNESGetApplicationContext(SNES snes, void *ctx)
1314d71ae5a4SJacob Faibussowitsch {
13153a40ed3dSBarry Smith   PetscFunctionBegin;
13160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1317*49abdd8aSBarry Smith   *(void **)ctx = snes->ctx;
13183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13199b94acceSBarry Smith }
132074679c65SBarry Smith 
13219b94acceSBarry Smith /*@
1322420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13233565c898SBarry Smith 
1324dc4c0fb0SBarry Smith   Logically Collective
13253565c898SBarry Smith 
13263565c898SBarry Smith   Input Parameters:
1327f6dfbefdSBarry Smith + snes        - `SNES` context
1328f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1329f6dfbefdSBarry 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
1330420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13313565c898SBarry Smith 
1332f6dfbefdSBarry Smith   Options Database Keys:
133301c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1334f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1335ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1336ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13373565c898SBarry Smith 
13383565c898SBarry Smith   Level: intermediate
13393565c898SBarry Smith 
1340f6dfbefdSBarry Smith   Note:
1341420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1342420bcc1bSBarry Smith   and computing explicitly with
1343f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1344ec5066bdSBarry Smith 
1345420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13463565c898SBarry Smith @*/
1347d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1348d71ae5a4SJacob Faibussowitsch {
13493565c898SBarry Smith   PetscFunctionBegin;
13503565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
135188b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
135288b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13534ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13543565c898SBarry Smith   snes->mf_operator = mf_operator;
13553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13563565c898SBarry Smith }
13573565c898SBarry Smith 
13583565c898SBarry Smith /*@
1359dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13603565c898SBarry Smith 
1361420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13623565c898SBarry Smith 
13633565c898SBarry Smith   Input Parameter:
1364f6dfbefdSBarry Smith . snes - `SNES` context
13653565c898SBarry Smith 
13663565c898SBarry Smith   Output Parameters:
1367f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1368f6dfbefdSBarry 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
13693565c898SBarry Smith 
13703565c898SBarry Smith   Level: intermediate
13713565c898SBarry Smith 
13721cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13733565c898SBarry Smith @*/
1374d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1375d71ae5a4SJacob Faibussowitsch {
13763565c898SBarry Smith   PetscFunctionBegin;
13773565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13783565c898SBarry Smith   if (mf) *mf = snes->mf;
13793565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13813565c898SBarry Smith }
13823565c898SBarry Smith 
13833565c898SBarry Smith /*@
1384420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13859b94acceSBarry Smith 
1386c7afd0dbSLois Curfman McInnes   Not Collective
1387c7afd0dbSLois Curfman McInnes 
13889b94acceSBarry Smith   Input Parameter:
1389f6dfbefdSBarry Smith . snes - `SNES` context
13909b94acceSBarry Smith 
13919b94acceSBarry Smith   Output Parameter:
13929b94acceSBarry Smith . iter - iteration number
13939b94acceSBarry Smith 
1394dc4c0fb0SBarry Smith   Level: intermediate
1395dc4c0fb0SBarry Smith 
1396c8228a4eSBarry Smith   Notes:
1397c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1398c8228a4eSBarry Smith 
1399c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1400f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
140108405cd6SLois Curfman McInnes .vb
140208405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
140308405cd6SLois Curfman McInnes       if (!(it % 2)) {
140408405cd6SLois Curfman McInnes         [compute Jacobian here]
140508405cd6SLois Curfman McInnes       }
140608405cd6SLois Curfman McInnes .ve
1407f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1408f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1409c8228a4eSBarry Smith 
1410f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1411c04deec6SBarry Smith 
1412420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14139b94acceSBarry Smith @*/
1414d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1415d71ae5a4SJacob Faibussowitsch {
14163a40ed3dSBarry Smith   PetscFunctionBegin;
14170700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14184f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14199b94acceSBarry Smith   *iter = snes->iter;
14203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14219b94acceSBarry Smith }
142274679c65SBarry Smith 
1423360c497dSPeter Brune /*@
1424360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1425360c497dSPeter Brune 
1426360c497dSPeter Brune   Not Collective
1427360c497dSPeter Brune 
1428d8d19677SJose E. Roman   Input Parameters:
1429f6dfbefdSBarry Smith + snes - `SNES` context
1430a2b725a8SWilliam Gropp - iter - iteration number
1431360c497dSPeter Brune 
1432360c497dSPeter Brune   Level: developer
1433360c497dSPeter Brune 
1434420bcc1bSBarry Smith   Note:
1435420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1436420bcc1bSBarry Smith 
14371cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1438360c497dSPeter Brune @*/
1439d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1440d71ae5a4SJacob Faibussowitsch {
1441360c497dSPeter Brune   PetscFunctionBegin;
1442360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14439566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1444360c497dSPeter Brune   snes->iter = iter;
14459566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1447360c497dSPeter Brune }
1448360c497dSPeter Brune 
14499b94acceSBarry Smith /*@
1450b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1451420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14529b94acceSBarry Smith 
1453c7afd0dbSLois Curfman McInnes   Not Collective
1454c7afd0dbSLois Curfman McInnes 
14559b94acceSBarry Smith   Input Parameter:
1456f6dfbefdSBarry Smith . snes - `SNES` context
14579b94acceSBarry Smith 
14589b94acceSBarry Smith   Output Parameter:
14599b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14609b94acceSBarry Smith 
1461dc4c0fb0SBarry Smith   Level: intermediate
1462dc4c0fb0SBarry Smith 
1463f6dfbefdSBarry Smith   Note:
1464f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1465c96a6f78SLois Curfman McInnes 
14661cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1467db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14689b94acceSBarry Smith @*/
1469d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1470d71ae5a4SJacob Faibussowitsch {
14713a40ed3dSBarry Smith   PetscFunctionBegin;
14720700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14734f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
147450ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147650ffb88aSMatthew Knepley }
147750ffb88aSMatthew Knepley 
147850ffb88aSMatthew Knepley /*@
1479b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1480420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
148150ffb88aSMatthew Knepley 
148250ffb88aSMatthew Knepley   Not Collective
148350ffb88aSMatthew Knepley 
148450ffb88aSMatthew Knepley   Input Parameters:
1485f6dfbefdSBarry Smith + snes     - `SNES` context
148677e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
148750ffb88aSMatthew Knepley 
1488420bcc1bSBarry Smith   Options Database Key:
1489420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1490420bcc1bSBarry Smith 
149150ffb88aSMatthew Knepley   Level: intermediate
149250ffb88aSMatthew Knepley 
1493420bcc1bSBarry Smith   Developer Note:
1494420bcc1bSBarry Smith   The options database key is wrong for this function name
1495420bcc1bSBarry Smith 
14961cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1497db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
149850ffb88aSMatthew Knepley @*/
1499d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1500d71ae5a4SJacob Faibussowitsch {
150150ffb88aSMatthew Knepley   PetscFunctionBegin;
15020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
150377e5a1f9SBarry Smith 
150477e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
15051690c2aeSBarry Smith     snes->maxFailures = PETSC_INT_MAX;
150677e5a1f9SBarry Smith   } else {
150777e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
150850ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
150977e5a1f9SBarry Smith   }
15103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151150ffb88aSMatthew Knepley }
151250ffb88aSMatthew Knepley 
151350ffb88aSMatthew Knepley /*@
1514b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1515420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
151650ffb88aSMatthew Knepley 
151750ffb88aSMatthew Knepley   Not Collective
151850ffb88aSMatthew Knepley 
151950ffb88aSMatthew Knepley   Input Parameter:
152020f4b53cSBarry Smith . snes - `SNES` context
152150ffb88aSMatthew Knepley 
152250ffb88aSMatthew Knepley   Output Parameter:
152350ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
152450ffb88aSMatthew Knepley 
152550ffb88aSMatthew Knepley   Level: intermediate
152650ffb88aSMatthew Knepley 
15271cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1528db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
152950ffb88aSMatthew Knepley @*/
1530d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1531d71ae5a4SJacob Faibussowitsch {
153250ffb88aSMatthew Knepley   PetscFunctionBegin;
15330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15344f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
153550ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15379b94acceSBarry Smith }
1538a847f771SSatish Balay 
15392541af92SBarry Smith /*@
15402541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1541420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15422541af92SBarry Smith 
15432541af92SBarry Smith   Not Collective
15442541af92SBarry Smith 
15452541af92SBarry Smith   Input Parameter:
1546f6dfbefdSBarry Smith . snes - `SNES` context
15472541af92SBarry Smith 
15482541af92SBarry Smith   Output Parameter:
15492541af92SBarry Smith . nfuncs - number of evaluations
15502541af92SBarry Smith 
15512541af92SBarry Smith   Level: intermediate
15522541af92SBarry Smith 
1553f6dfbefdSBarry Smith   Note:
1554f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1555971e163fSPeter Brune 
15561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15572541af92SBarry Smith @*/
1558d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1559d71ae5a4SJacob Faibussowitsch {
15602541af92SBarry Smith   PetscFunctionBegin;
15610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15624f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15632541af92SBarry Smith   *nfuncs = snes->nfuncs;
15643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15652541af92SBarry Smith }
15662541af92SBarry Smith 
15673d4c4710SBarry Smith /*@
15683d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1569420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15703d4c4710SBarry Smith 
15713d4c4710SBarry Smith   Not Collective
15723d4c4710SBarry Smith 
15733d4c4710SBarry Smith   Input Parameter:
1574f6dfbefdSBarry Smith . snes - `SNES` context
15753d4c4710SBarry Smith 
15763d4c4710SBarry Smith   Output Parameter:
15773d4c4710SBarry Smith . nfails - number of failed solves
15783d4c4710SBarry Smith 
1579f6dfbefdSBarry Smith   Options Database Key:
15809d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15819d85da0cSMatthew G. Knepley 
1582f6dfbefdSBarry Smith   Level: intermediate
1583f6dfbefdSBarry Smith 
1584f6dfbefdSBarry Smith   Note:
1585f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15863d4c4710SBarry Smith 
15871cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15883d4c4710SBarry Smith @*/
1589d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1590d71ae5a4SJacob Faibussowitsch {
15913d4c4710SBarry Smith   PetscFunctionBegin;
15920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15934f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15943d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15963d4c4710SBarry Smith }
15973d4c4710SBarry Smith 
15983d4c4710SBarry Smith /*@
15993d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1600f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
16013d4c4710SBarry Smith 
1602c3339decSBarry Smith   Logically Collective
16033d4c4710SBarry Smith 
16043d4c4710SBarry Smith   Input Parameters:
1605f6dfbefdSBarry Smith + snes     - `SNES` context
160677e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16073d4c4710SBarry Smith 
1608f6dfbefdSBarry Smith   Options Database Key:
16099d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16109d85da0cSMatthew G. Knepley 
1611dc4c0fb0SBarry Smith   Level: intermediate
1612dc4c0fb0SBarry Smith 
1613f6dfbefdSBarry Smith   Note:
1614f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16153d4c4710SBarry Smith 
1616420bcc1bSBarry Smith   Developer Note:
1617420bcc1bSBarry Smith   The options database key is wrong for this function name
1618420bcc1bSBarry Smith 
16191cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16203d4c4710SBarry Smith @*/
1621d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1622d71ae5a4SJacob Faibussowitsch {
16233d4c4710SBarry Smith   PetscFunctionBegin;
16240700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1625c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
162677e5a1f9SBarry Smith 
162777e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
16281690c2aeSBarry Smith     snes->maxLinearSolveFailures = PETSC_INT_MAX;
162977e5a1f9SBarry Smith   } else {
163077e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16313d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
163277e5a1f9SBarry Smith   }
16333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16343d4c4710SBarry Smith }
16353d4c4710SBarry Smith 
16363d4c4710SBarry Smith /*@
16373d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1638f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16393d4c4710SBarry Smith 
16403d4c4710SBarry Smith   Not Collective
16413d4c4710SBarry Smith 
16423d4c4710SBarry Smith   Input Parameter:
1643f6dfbefdSBarry Smith . snes - `SNES` context
16443d4c4710SBarry Smith 
16453d4c4710SBarry Smith   Output Parameter:
16463d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16473d4c4710SBarry Smith 
16483d4c4710SBarry Smith   Level: intermediate
16493d4c4710SBarry Smith 
1650f6dfbefdSBarry Smith   Note:
1651f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16523d4c4710SBarry Smith 
16531cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16543d4c4710SBarry Smith @*/
1655d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1656d71ae5a4SJacob Faibussowitsch {
16573d4c4710SBarry Smith   PetscFunctionBegin;
16580700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16594f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16603d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16623d4c4710SBarry Smith }
16633d4c4710SBarry Smith 
1664c96a6f78SLois Curfman McInnes /*@
1665b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1666420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1667c96a6f78SLois Curfman McInnes 
1668c7afd0dbSLois Curfman McInnes   Not Collective
1669c7afd0dbSLois Curfman McInnes 
1670c96a6f78SLois Curfman McInnes   Input Parameter:
1671f6dfbefdSBarry Smith . snes - `SNES` context
1672c96a6f78SLois Curfman McInnes 
1673c96a6f78SLois Curfman McInnes   Output Parameter:
1674c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1675c96a6f78SLois Curfman McInnes 
1676dc4c0fb0SBarry Smith   Level: intermediate
1677dc4c0fb0SBarry Smith 
1678c96a6f78SLois Curfman McInnes   Notes:
1679f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1680c96a6f78SLois Curfman McInnes 
1681f6dfbefdSBarry 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
1682f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1683010be392SBarry Smith 
16841cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1685c96a6f78SLois Curfman McInnes @*/
1686d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1687d71ae5a4SJacob Faibussowitsch {
16883a40ed3dSBarry Smith   PetscFunctionBegin;
16890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16904f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1691c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1693c96a6f78SLois Curfman McInnes }
1694c96a6f78SLois Curfman McInnes 
1695971e163fSPeter Brune /*@
1696971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1697f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1698971e163fSPeter Brune 
1699c3339decSBarry Smith   Logically Collective
1700971e163fSPeter Brune 
1701d8d19677SJose E. Roman   Input Parameters:
1702f6dfbefdSBarry Smith + snes  - `SNES` context
1703f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1704971e163fSPeter Brune 
1705971e163fSPeter Brune   Level: developer
1706971e163fSPeter Brune 
17071cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1708971e163fSPeter Brune @*/
1709d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1710d71ae5a4SJacob Faibussowitsch {
1711971e163fSPeter Brune   PetscFunctionBegin;
1712971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1713971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1714971e163fSPeter Brune   snes->counters_reset = reset;
17153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1716971e163fSPeter Brune }
1717971e163fSPeter Brune 
17182999313aSBarry Smith /*@
171912b1dd1aSStefano Zampini   SNESResetCounters - Reset counters for linear iterations and function evaluations.
172012b1dd1aSStefano Zampini 
172112b1dd1aSStefano Zampini   Logically Collective
172212b1dd1aSStefano Zampini 
172312b1dd1aSStefano Zampini   Input Parameters:
172412b1dd1aSStefano Zampini . snes - `SNES` context
172512b1dd1aSStefano Zampini 
172612b1dd1aSStefano Zampini   Level: developer
172712b1dd1aSStefano Zampini 
172812b1dd1aSStefano Zampini   Note:
172912b1dd1aSStefano Zampini   It honors the flag set with `SNESSetCountersReset()`
173012b1dd1aSStefano Zampini 
173112b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
173212b1dd1aSStefano Zampini @*/
173312b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
173412b1dd1aSStefano Zampini {
173512b1dd1aSStefano Zampini   PetscFunctionBegin;
173612b1dd1aSStefano Zampini   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
173712b1dd1aSStefano Zampini   if (snes->counters_reset) {
173812b1dd1aSStefano Zampini     snes->nfuncs      = 0;
173912b1dd1aSStefano Zampini     snes->linear_its  = 0;
174012b1dd1aSStefano Zampini     snes->numFailures = 0;
174112b1dd1aSStefano Zampini   }
174212b1dd1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
174312b1dd1aSStefano Zampini }
174412b1dd1aSStefano Zampini 
174512b1dd1aSStefano Zampini /*@
1746f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17472999313aSBarry Smith 
1748420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17492999313aSBarry Smith 
17502999313aSBarry Smith   Input Parameters:
1751f6dfbefdSBarry Smith + snes - the `SNES` context
1752f6dfbefdSBarry Smith - ksp  - the `KSP` context
17532999313aSBarry Smith 
1754dc4c0fb0SBarry Smith   Level: developer
1755dc4c0fb0SBarry Smith 
17562999313aSBarry Smith   Notes:
1757f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17582999313aSBarry Smith   so this routine is rarely needed.
17592999313aSBarry Smith 
1760f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1761420bcc1bSBarry Smith   decreased by one when this is called.
17622999313aSBarry Smith 
176342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17642999313aSBarry Smith @*/
1765d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1766d71ae5a4SJacob Faibussowitsch {
17672999313aSBarry Smith   PetscFunctionBegin;
17680700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17690700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17702999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17729566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17732999313aSBarry Smith   snes->ksp = ksp;
17743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17752999313aSBarry Smith }
17762999313aSBarry Smith 
177752baeb72SSatish Balay /*@
177877e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
177977e5a1f9SBarry Smith   currently contain default values
178077e5a1f9SBarry Smith 
178177e5a1f9SBarry Smith   Collective
178277e5a1f9SBarry Smith 
178377e5a1f9SBarry Smith   Input Parameter:
178477e5a1f9SBarry Smith . snes - the `SNES` object
178577e5a1f9SBarry Smith 
178677e5a1f9SBarry Smith   Level: developer
178777e5a1f9SBarry Smith 
178877e5a1f9SBarry Smith   Developer Note:
178977e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
179077e5a1f9SBarry Smith 
179177e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
179277e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
179377e5a1f9SBarry Smith @*/
179477e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
179577e5a1f9SBarry Smith {
179677e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
179777e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
179877e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
179977e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
180077e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
180177e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
180277e5a1f9SBarry Smith   return PETSC_SUCCESS;
180377e5a1f9SBarry Smith }
180477e5a1f9SBarry Smith 
180577e5a1f9SBarry Smith /*@
1806dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
18079b94acceSBarry Smith 
1808d083f849SBarry Smith   Collective
1809c7afd0dbSLois Curfman McInnes 
1810f6dfbefdSBarry Smith   Input Parameter:
1811906ed7ccSBarry Smith . comm - MPI communicator
18129b94acceSBarry Smith 
18139b94acceSBarry Smith   Output Parameter:
181420f4b53cSBarry Smith . outsnes - the new `SNES` context
18159b94acceSBarry Smith 
1816c7afd0dbSLois Curfman McInnes   Options Database Keys:
1817dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1818dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1819dc4c0fb0SBarry Smith                       as set by `SNESSetJacobian()`
1820dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1821c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1822c1f60f51SBarry Smith 
182336851e7fSLois Curfman McInnes   Level: beginner
182436851e7fSLois Curfman McInnes 
182595452b02SPatrick Sanan   Developer Notes:
1826f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1827efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1828f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1829f6dfbefdSBarry Smith   in `SNESView()`.
1830efd4aadfSBarry Smith 
1831f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1832f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1833f6dfbefdSBarry Smith 
1834dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1835efd4aadfSBarry Smith 
1836e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18379b94acceSBarry Smith @*/
1838d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1839d71ae5a4SJacob Faibussowitsch {
18409b94acceSBarry Smith   SNES       snes;
1841fa9f3622SBarry Smith   SNESKSPEW *kctx;
184237fcc0dbSBarry Smith 
18433a40ed3dSBarry Smith   PetscFunctionBegin;
18444f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18459566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18468ba1e511SMatthew Knepley 
18479566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18488d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18492c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18509b94acceSBarry Smith   snes->norm           = 0.0;
1851c1e67a49SFande Kong   snes->xnorm          = 0.0;
1852c1e67a49SFande Kong   snes->ynorm          = 0.0;
1853365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18546c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1855b4874afaSBarry Smith   snes->ttol           = 0.0;
185677e5a1f9SBarry Smith 
1857e37c518bSBarry Smith   snes->rnorm0               = 0;
18589b94acceSBarry Smith   snes->nfuncs               = 0;
185950ffb88aSMatthew Knepley   snes->numFailures          = 0;
186050ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18617a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1862e35cf81dSBarry Smith   snes->lagjacobian          = 1;
186337ec4e1aSPeter Brune   snes->jac_iter             = 0;
186437ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1865a8054027SBarry Smith   snes->lagpreconditioner    = 1;
186637ec4e1aSPeter Brune   snes->pre_iter             = 0;
186737ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1868639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1869c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18709e5d0892SLisandro Dalcin   snes->data                 = NULL;
18714dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1872186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18736f24a144SLois Curfman McInnes   snes->nwork                = 0;
18749e5d0892SLisandro Dalcin   snes->work                 = NULL;
187558c9b817SLisandro Dalcin   snes->nvwork               = 0;
18769e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1877758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1878758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18790298fd71SBarry Smith   snes->conv_hist            = NULL;
18800298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1881758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1882971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1883e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1884184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1885efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1886b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1887c40d0f55SPeter Brune 
1888d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1889d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1890d8f46077SPeter Brune   snes->mf_version  = 1;
1891d8f46077SPeter Brune 
18923d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18933d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18943d4c4710SBarry Smith 
1895349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
189676bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1897349187a7SBarry Smith 
18984fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
18994fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
19004fc747eaSLawrence Mitchell 
19019b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
19024dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1903f5af7f23SKarl Rupp 
19049b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
19059b94acceSBarry Smith   kctx->version     = 2;
19060f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
19079b94acceSBarry Smith                              this was too large for some test cases */
190875567043SBarry Smith   kctx->rtol_last   = 0.0;
19090f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
19109b94acceSBarry Smith   kctx->gamma       = 1.0;
19110f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
191271f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
19130f0abf79SStefano Zampini   kctx->threshold   = 0.1;
191475567043SBarry Smith   kctx->lresid_last = 0.0;
191575567043SBarry Smith   kctx->norm_last   = 0.0;
19169b94acceSBarry Smith 
19170f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
19180f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
19190f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
19200f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
19210f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19220f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19230f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19240f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19250f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19260f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19270f0abf79SStefano Zampini 
19289b94acceSBarry Smith   *outsnes = snes;
19293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19309b94acceSBarry Smith }
19319b94acceSBarry Smith 
19329b94acceSBarry Smith /*@C
19339b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1934f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19359b94acceSBarry Smith   equations.
19369b94acceSBarry Smith 
1937c3339decSBarry Smith   Logically Collective
1938fee21e36SBarry Smith 
1939c7afd0dbSLois Curfman McInnes   Input Parameters:
1940f6dfbefdSBarry Smith + snes - the `SNES` context
1941dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19428434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1943c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1944dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19459b94acceSBarry Smith 
194636851e7fSLois Curfman McInnes   Level: beginner
194736851e7fSLois Curfman McInnes 
19488434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19499b94acceSBarry Smith @*/
19508434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1951d71ae5a4SJacob Faibussowitsch {
19526cab3a1bSJed Brown   DM dm;
19536cab3a1bSJed Brown 
19543a40ed3dSBarry Smith   PetscFunctionBegin;
19550700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1956d2a683ecSLisandro Dalcin   if (r) {
1957d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1958d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19599566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19609566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
196185385478SLisandro Dalcin     snes->vec_func = r;
1962d2a683ecSLisandro Dalcin   }
19639566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19649566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
196548a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19679b94acceSBarry Smith }
19689b94acceSBarry Smith 
1969e4ed7901SPeter Brune /*@C
19700b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1971e4ed7901SPeter Brune 
1972c3339decSBarry Smith   Logically Collective
1973e4ed7901SPeter Brune 
1974e4ed7901SPeter Brune   Input Parameters:
1975f6dfbefdSBarry Smith + snes - the `SNES` context
1976e4ed7901SPeter Brune - f    - vector to store function value
1977e4ed7901SPeter Brune 
1978dc4c0fb0SBarry Smith   Level: developer
1979dc4c0fb0SBarry Smith 
1980e4ed7901SPeter Brune   Notes:
1981e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1982e4ed7901SPeter Brune 
1983f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1984e4ed7901SPeter Brune 
19851cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1986e4ed7901SPeter Brune @*/
1987d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1988d71ae5a4SJacob Faibussowitsch {
1989e4ed7901SPeter Brune   Vec vec_func;
1990e4ed7901SPeter Brune 
1991e4ed7901SPeter Brune   PetscFunctionBegin;
1992e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1993e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1994e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1995efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
1996902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
19973ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1998902f982fSPeter Brune   }
19999566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
20009566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
2001f5af7f23SKarl Rupp 
2002217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
20033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2004e4ed7901SPeter Brune }
2005e4ed7901SPeter Brune 
2006534ebe21SPeter Brune /*@
2007f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
2008f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
2009534ebe21SPeter Brune 
2010c3339decSBarry Smith   Logically Collective
2011534ebe21SPeter Brune 
2012534ebe21SPeter Brune   Input Parameters:
2013f6dfbefdSBarry Smith + snes         - the `SNES` context
2014365a6726SPeter Brune - normschedule - the frequency of norm computation
2015534ebe21SPeter Brune 
2016517f1916SMatthew G. Knepley   Options Database Key:
201767b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2018517f1916SMatthew G. Knepley 
2019dc4c0fb0SBarry Smith   Level: advanced
2020dc4c0fb0SBarry Smith 
2021534ebe21SPeter Brune   Notes:
2022f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2023534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2024534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2025f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2026534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2027534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2028534ebe21SPeter Brune   their solution.
2029534ebe21SPeter Brune 
2030e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2031534ebe21SPeter Brune @*/
2032d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2033d71ae5a4SJacob Faibussowitsch {
2034534ebe21SPeter Brune   PetscFunctionBegin;
2035534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2036365a6726SPeter Brune   snes->normschedule = normschedule;
20373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2038534ebe21SPeter Brune }
2039534ebe21SPeter Brune 
2040534ebe21SPeter Brune /*@
2041f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2042f6dfbefdSBarry Smith   of the `SNES` method.
2043534ebe21SPeter Brune 
2044c3339decSBarry Smith   Logically Collective
2045534ebe21SPeter Brune 
2046534ebe21SPeter Brune   Input Parameters:
2047f6dfbefdSBarry Smith + snes         - the `SNES` context
2048365a6726SPeter Brune - normschedule - the type of the norm used
2049534ebe21SPeter Brune 
2050534ebe21SPeter Brune   Level: advanced
2051534ebe21SPeter Brune 
20521cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2053534ebe21SPeter Brune @*/
2054d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2055d71ae5a4SJacob Faibussowitsch {
2056534ebe21SPeter Brune   PetscFunctionBegin;
2057534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2058365a6726SPeter Brune   *normschedule = snes->normschedule;
20593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2060534ebe21SPeter Brune }
2061534ebe21SPeter Brune 
2062c5ce4427SMatthew G. Knepley /*@
2063c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2064c5ce4427SMatthew G. Knepley 
2065c3339decSBarry Smith   Logically Collective
2066c5ce4427SMatthew G. Knepley 
2067c5ce4427SMatthew G. Knepley   Input Parameters:
2068f6dfbefdSBarry Smith + snes - the `SNES` context
2069f6dfbefdSBarry Smith - norm - the value of the norm
2070c5ce4427SMatthew G. Knepley 
2071c5ce4427SMatthew G. Knepley   Level: developer
2072c5ce4427SMatthew G. Knepley 
20731cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2074c5ce4427SMatthew G. Knepley @*/
2075d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2076d71ae5a4SJacob Faibussowitsch {
2077c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2078c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2079c5ce4427SMatthew G. Knepley   snes->norm = norm;
20803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2081c5ce4427SMatthew G. Knepley }
2082c5ce4427SMatthew G. Knepley 
2083c5ce4427SMatthew G. Knepley /*@
2084c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2085c5ce4427SMatthew G. Knepley 
2086c5ce4427SMatthew G. Knepley   Not Collective
2087c5ce4427SMatthew G. Knepley 
2088c5ce4427SMatthew G. Knepley   Input Parameter:
2089f6dfbefdSBarry Smith . snes - the `SNES` context
2090c5ce4427SMatthew G. Knepley 
2091c5ce4427SMatthew G. Knepley   Output Parameter:
2092c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2093c5ce4427SMatthew G. Knepley 
2094c5ce4427SMatthew G. Knepley   Level: developer
2095c5ce4427SMatthew G. Knepley 
20961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2097c5ce4427SMatthew G. Knepley @*/
2098d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2099d71ae5a4SJacob Faibussowitsch {
2100c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2101c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21024f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2103c5ce4427SMatthew G. Knepley   *norm = snes->norm;
21043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2105c5ce4427SMatthew G. Knepley }
2106c5ce4427SMatthew G. Knepley 
2107c1e67a49SFande Kong /*@
2108f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2109c1e67a49SFande Kong 
2110c1e67a49SFande Kong   Not Collective
2111c1e67a49SFande Kong 
2112c1e67a49SFande Kong   Input Parameter:
2113f6dfbefdSBarry Smith . snes - the `SNES` context
2114c1e67a49SFande Kong 
2115c1e67a49SFande Kong   Output Parameter:
2116c1e67a49SFande Kong . ynorm - the last computed update norm
2117c1e67a49SFande Kong 
2118c1e67a49SFande Kong   Level: developer
2119c1e67a49SFande Kong 
2120f6dfbefdSBarry Smith   Note:
2121f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2122f6dfbefdSBarry Smith 
21231cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2124c1e67a49SFande Kong @*/
2125d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2126d71ae5a4SJacob Faibussowitsch {
2127c1e67a49SFande Kong   PetscFunctionBegin;
2128c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21294f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2130c1e67a49SFande Kong   *ynorm = snes->ynorm;
21313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2132c1e67a49SFande Kong }
2133c1e67a49SFande Kong 
2134c1e67a49SFande Kong /*@
21354591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2136c1e67a49SFande Kong 
2137c1e67a49SFande Kong   Not Collective
2138c1e67a49SFande Kong 
2139c1e67a49SFande Kong   Input Parameter:
2140f6dfbefdSBarry Smith . snes - the `SNES` context
2141c1e67a49SFande Kong 
2142c1e67a49SFande Kong   Output Parameter:
2143c1e67a49SFande Kong . xnorm - the last computed solution norm
2144c1e67a49SFande Kong 
2145c1e67a49SFande Kong   Level: developer
2146c1e67a49SFande Kong 
21471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2148c1e67a49SFande Kong @*/
2149d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2150d71ae5a4SJacob Faibussowitsch {
2151c1e67a49SFande Kong   PetscFunctionBegin;
2152c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21534f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2154c1e67a49SFande Kong   *xnorm = snes->xnorm;
21553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2156c1e67a49SFande Kong }
2157c1e67a49SFande Kong 
2158cc4c1da9SBarry Smith /*@
2159f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2160f6dfbefdSBarry Smith   of the `SNES` method.
216147073ea2SPeter Brune 
2162c3339decSBarry Smith   Logically Collective
216347073ea2SPeter Brune 
216447073ea2SPeter Brune   Input Parameters:
2165f6dfbefdSBarry Smith + snes - the `SNES` context
2166f6dfbefdSBarry Smith - type - the function type
216747073ea2SPeter Brune 
216847073ea2SPeter Brune   Level: developer
216947073ea2SPeter Brune 
2170420bcc1bSBarry Smith   Values of the function type\:
2171f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2172f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2173f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2174f6dfbefdSBarry Smith 
2175420bcc1bSBarry Smith   Note:
2176f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2177f6dfbefdSBarry Smith 
21781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
217947073ea2SPeter Brune @*/
2180d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2181d71ae5a4SJacob Faibussowitsch {
218247073ea2SPeter Brune   PetscFunctionBegin;
218347073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
218447073ea2SPeter Brune   snes->functype = type;
21853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218647073ea2SPeter Brune }
218747073ea2SPeter Brune 
2188cc4c1da9SBarry Smith /*@
2189f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
219047073ea2SPeter Brune   of the SNES method.
219147073ea2SPeter Brune 
2192c3339decSBarry Smith   Logically Collective
219347073ea2SPeter Brune 
219447073ea2SPeter Brune   Input Parameters:
2195f6dfbefdSBarry Smith + snes - the `SNES` context
2196f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
219747073ea2SPeter Brune 
219847073ea2SPeter Brune   Level: advanced
219947073ea2SPeter Brune 
22001cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
220147073ea2SPeter Brune @*/
2202d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2203d71ae5a4SJacob Faibussowitsch {
220447073ea2SPeter Brune   PetscFunctionBegin;
220547073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
220647073ea2SPeter Brune   *type = snes->functype;
22073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2208534ebe21SPeter Brune }
2209534ebe21SPeter Brune 
2210c79ef259SPeter Brune /*@C
2211be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2212c79ef259SPeter Brune   use with composed nonlinear solvers.
2213c79ef259SPeter Brune 
2214c79ef259SPeter Brune   Input Parameters:
22159bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22168434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
221777e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2218c79ef259SPeter Brune 
2219dc4c0fb0SBarry Smith   Level: intermediate
2220dc4c0fb0SBarry Smith 
2221f6dfbefdSBarry Smith   Note:
2222f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2223f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2224c79ef259SPeter Brune 
22258434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2226c79ef259SPeter Brune @*/
22278434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2228d71ae5a4SJacob Faibussowitsch {
22296cab3a1bSJed Brown   DM dm;
22306cab3a1bSJed Brown 
2231646217ecSPeter Brune   PetscFunctionBegin;
22326cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22339566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22349566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2236646217ecSPeter Brune }
2237646217ecSPeter Brune 
2238bbc1464cSBarry Smith /*
2239bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2240bbc1464cSBarry Smith    changed during the KSPSolve()
2241bbc1464cSBarry Smith */
2242d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2243d71ae5a4SJacob Faibussowitsch {
2244bbc1464cSBarry Smith   DM     dm;
2245bbc1464cSBarry Smith   DMSNES sdm;
2246bbc1464cSBarry Smith 
2247bbc1464cSBarry Smith   PetscFunctionBegin;
22489566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22499566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2250bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2251bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2252792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22539566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22540df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2255ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2256792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22579566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2258bbc1464cSBarry Smith   } else {
2259792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22609566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2261bbc1464cSBarry Smith   }
22623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2263bbc1464cSBarry Smith }
2264bbc1464cSBarry Smith 
2265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2266d71ae5a4SJacob Faibussowitsch {
2267e03ab78fSPeter Brune   DM     dm;
2268942e3340SBarry Smith   DMSNES sdm;
22696cab3a1bSJed Brown 
22708b0a5094SBarry Smith   PetscFunctionBegin;
22719566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22729566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22738b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2274bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2275792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22769566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2277792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22789566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2279bbc1464cSBarry Smith   } else {
2280792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22819566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2282bbc1464cSBarry Smith   }
22833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22848b0a5094SBarry Smith }
22858b0a5094SBarry Smith 
2286d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2287d71ae5a4SJacob Faibussowitsch {
22888b0a5094SBarry Smith   PetscFunctionBegin;
2289e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2290bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22919566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22948b0a5094SBarry Smith }
22958b0a5094SBarry Smith 
22968b0a5094SBarry Smith /*@C
22971d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
22988b0a5094SBarry Smith 
2299c3339decSBarry Smith   Logically Collective
23008b0a5094SBarry Smith 
23018b0a5094SBarry Smith   Input Parameters:
2302f6dfbefdSBarry Smith + snes - the `SNES` context
2303dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
23048434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
23056b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2306dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
23078434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2308dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2309dc4c0fb0SBarry Smith 
2310dc4c0fb0SBarry Smith   Level: intermediate
23118b0a5094SBarry Smith 
23128b0a5094SBarry Smith   Notes:
23136b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2314f450aa47SBarry 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.
2315f450aa47SBarry Smith 
2316f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23178b0a5094SBarry Smith 
23181d27aa22SBarry 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}$.
23191d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23208b0a5094SBarry Smith 
2321dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
23228b0a5094SBarry Smith 
23230d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23241d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23258b0a5094SBarry Smith 
23268b0a5094SBarry 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
23271d27aa22SBarry 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
23281d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23298b0a5094SBarry Smith 
23301d27aa22SBarry 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
2331f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
23326b7fb656SBarry Smith 
233315229ffcSPierre 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.
23346b7fb656SBarry Smith 
2335dc4c0fb0SBarry 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
23366b7fb656SBarry 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
2337f6dfbefdSBarry 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`.
2338aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2339bbc1464cSBarry Smith 
23409bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23418434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23428b0a5094SBarry Smith @*/
23438434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2344d71ae5a4SJacob Faibussowitsch {
2345e03ab78fSPeter Brune   DM dm;
2346e03ab78fSPeter Brune 
23478b0a5094SBarry Smith   PetscFunctionBegin;
23488b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23499566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23509566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23519566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23529566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23539566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23558b0a5094SBarry Smith }
23568b0a5094SBarry Smith 
23577971a8bfSPeter Brune /*@C
23587971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23597971a8bfSPeter Brune 
2360f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23617971a8bfSPeter Brune 
23627971a8bfSPeter Brune   Input Parameter:
2363f6dfbefdSBarry Smith . snes - the `SNES` context
23647971a8bfSPeter Brune 
2365d8d19677SJose E. Roman   Output Parameters:
2366dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23678434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2368dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2369dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23708434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2371dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23727971a8bfSPeter Brune 
23737971a8bfSPeter Brune   Level: advanced
23747971a8bfSPeter Brune 
23758434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23767971a8bfSPeter Brune @*/
23778434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2378d71ae5a4SJacob Faibussowitsch {
23797971a8bfSPeter Brune   DM dm;
23807971a8bfSPeter Brune 
23817971a8bfSPeter Brune   PetscFunctionBegin;
23827971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23839566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23849566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23859566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23869566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23887971a8bfSPeter Brune }
23897971a8bfSPeter Brune 
2390d25893d9SBarry Smith /*@C
2391dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2392d25893d9SBarry Smith 
2393c3339decSBarry Smith   Logically Collective
2394d25893d9SBarry Smith 
2395d25893d9SBarry Smith   Input Parameters:
2396f6dfbefdSBarry Smith + snes - the `SNES` context
23978434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2398d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2399dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2400d25893d9SBarry Smith 
2401d25893d9SBarry Smith   Level: intermediate
2402d25893d9SBarry Smith 
24038434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2404d25893d9SBarry Smith @*/
24058434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2406d71ae5a4SJacob Faibussowitsch {
2407d25893d9SBarry Smith   PetscFunctionBegin;
2408d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2409d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2410d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
24113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2412d25893d9SBarry Smith }
2413d25893d9SBarry Smith 
24141096aae1SMatthew Knepley /*@C
2415dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2416dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
24171096aae1SMatthew Knepley 
2418c3339decSBarry Smith   Logically Collective
24191096aae1SMatthew Knepley 
24201096aae1SMatthew Knepley   Input Parameter:
2421f6dfbefdSBarry Smith . snes - the `SNES` context
24221096aae1SMatthew Knepley 
24231096aae1SMatthew Knepley   Output Parameter:
2424dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24251096aae1SMatthew Knepley 
24261096aae1SMatthew Knepley   Level: intermediate
24271096aae1SMatthew Knepley 
24281cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24291096aae1SMatthew Knepley @*/
2430d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2431d71ae5a4SJacob Faibussowitsch {
24321096aae1SMatthew Knepley   PetscFunctionBegin;
24330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24344f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
243585385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24371096aae1SMatthew Knepley }
24381096aae1SMatthew Knepley 
24399b94acceSBarry Smith /*@
2440f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24419b94acceSBarry Smith 
2442c3339decSBarry Smith   Collective
2443c7afd0dbSLois Curfman McInnes 
24449b94acceSBarry Smith   Input Parameters:
2445f6dfbefdSBarry Smith + snes - the `SNES` context
2446c7afd0dbSLois Curfman McInnes - x    - input vector
24479b94acceSBarry Smith 
24489b94acceSBarry Smith   Output Parameter:
2449f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24509b94acceSBarry Smith 
2451dc4c0fb0SBarry Smith   Level: developer
2452dc4c0fb0SBarry Smith 
245300677de2SStefano Zampini   Notes:
2454f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2455bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
245636851e7fSLois Curfman McInnes 
245700677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
245800677de2SStefano Zampini 
24591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24609b94acceSBarry Smith @*/
2461d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2462d71ae5a4SJacob Faibussowitsch {
24636cab3a1bSJed Brown   DM     dm;
2464942e3340SBarry Smith   DMSNES sdm;
24659b94acceSBarry Smith 
24663a40ed3dSBarry Smith   PetscFunctionBegin;
24670700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24680700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24690700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2470c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2471c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2472e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2473184914b5SBarry Smith 
24749566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24759566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24760fdf79fbSJacob 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().");
247732f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
247848a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24799566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24808ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24818ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2482800f99ffSJeremy L Thompson     {
2483800f99ffSJeremy L Thompson       void           *ctx;
24848434afd1SBarry Smith       SNESFunctionFn *computefunction;
2485800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2486800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2487800f99ffSJeremy L Thompson     }
24889566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
248948a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24900fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24919566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24920fdf79fbSJacob Faibussowitsch   }
24931baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2494ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2495422a814eSBarry Smith   /*
2496422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2497422a814eSBarry Smith      propagate the value to all processes
2498422a814eSBarry Smith   */
2499f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25019b94acceSBarry Smith }
25029b94acceSBarry Smith 
2503c79ef259SPeter Brune /*@
2504f6dfbefdSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `SNESSetMFFunction()`.
2505bbc1464cSBarry Smith 
2506c3339decSBarry Smith   Collective
2507bbc1464cSBarry Smith 
2508bbc1464cSBarry Smith   Input Parameters:
2509f6dfbefdSBarry Smith + snes - the `SNES` context
2510bbc1464cSBarry Smith - x    - input vector
2511bbc1464cSBarry Smith 
2512bbc1464cSBarry Smith   Output Parameter:
2513f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetMFFunction()`
2514bbc1464cSBarry Smith 
2515dc4c0fb0SBarry Smith   Level: developer
2516dc4c0fb0SBarry Smith 
2517bbc1464cSBarry Smith   Notes:
2518420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2519bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2520bbc1464cSBarry Smith 
2521dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2522f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2523dd8e379bSPierre 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.
2524bbc1464cSBarry Smith 
25251cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF`
2526bbc1464cSBarry Smith @*/
2527d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2528d71ae5a4SJacob Faibussowitsch {
2529bbc1464cSBarry Smith   DM     dm;
2530bbc1464cSBarry Smith   DMSNES sdm;
2531bbc1464cSBarry Smith 
2532bbc1464cSBarry Smith   PetscFunctionBegin;
2533bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2534bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2535bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2536bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2537bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2538e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2539bbc1464cSBarry Smith 
25409566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25419566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25439566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2544bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2545bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2546792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25479566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25489566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2549bbc1464cSBarry Smith   snes->nfuncs++;
2550bbc1464cSBarry Smith   /*
2551bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2552bbc1464cSBarry Smith      propagate the value to all processes
2553bbc1464cSBarry Smith   */
2554f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2556bbc1464cSBarry Smith }
2557bbc1464cSBarry Smith 
2558bbc1464cSBarry Smith /*@
2559f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2560c79ef259SPeter Brune 
2561c3339decSBarry Smith   Collective
2562c79ef259SPeter Brune 
2563c79ef259SPeter Brune   Input Parameters:
2564f6dfbefdSBarry Smith + snes - the `SNES` context
2565c79ef259SPeter Brune . x    - input vector
2566c79ef259SPeter Brune - b    - rhs vector
2567c79ef259SPeter Brune 
2568c79ef259SPeter Brune   Output Parameter:
2569c79ef259SPeter Brune . x - new solution vector
2570c79ef259SPeter Brune 
2571dc4c0fb0SBarry Smith   Level: developer
2572dc4c0fb0SBarry Smith 
2573f6dfbefdSBarry Smith   Note:
2574f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2575c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2576c79ef259SPeter Brune   themselves.
2577c79ef259SPeter Brune 
25788434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2579c79ef259SPeter Brune @*/
2580d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2581d71ae5a4SJacob Faibussowitsch {
25826cab3a1bSJed Brown   DM     dm;
2583942e3340SBarry Smith   DMSNES sdm;
2584646217ecSPeter Brune 
2585646217ecSPeter Brune   PetscFunctionBegin;
2586646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2587064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2588064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2589064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2590064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2591e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25939566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25949566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25950fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
25969566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2597792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
25989566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
25999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
26003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2601646217ecSPeter Brune }
2602646217ecSPeter Brune 
2603494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2604494a190aSStefano Zampini {
2605494a190aSStefano Zampini   Vec          X;
2606494a190aSStefano Zampini   PetscScalar *g;
2607494a190aSStefano Zampini   PetscReal    f, f2;
2608494a190aSStefano Zampini   PetscInt     low, high, N, i;
2609494a190aSStefano Zampini   PetscBool    flg;
2610494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2611494a190aSStefano Zampini 
2612494a190aSStefano Zampini   PetscFunctionBegin;
2613494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2614494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2615494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2616494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2617494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2618494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2619494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2620494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2621494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2622494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2623494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2624494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2625494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2626494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2627494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2628494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2629494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2630494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2631494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2632494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2633494a190aSStefano Zampini   }
2634494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2635494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2636494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2637494a190aSStefano Zampini }
2638494a190aSStefano Zampini 
2639494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2640494a190aSStefano Zampini {
2641494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2642494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2643494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2644494a190aSStefano Zampini   PetscScalar       dot;
2645494a190aSStefano Zampini   MPI_Comm          comm;
2646494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2647494a190aSStefano Zampini   PetscViewerFormat format;
2648494a190aSStefano Zampini   PetscInt          tabs;
2649494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26508434afd1SBarry Smith   SNESObjectiveFn  *objective;
2651494a190aSStefano Zampini 
2652494a190aSStefano Zampini   PetscFunctionBegin;
2653494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2654494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2655494a190aSStefano Zampini 
2656494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2657494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2658494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2659494a190aSStefano Zampini   PetscOptionsEnd();
2660494a190aSStefano Zampini   if (!test) {
2661494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2662494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2663494a190aSStefano Zampini   }
2664494a190aSStefano Zampini 
2665494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2666494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2667494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2668494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2669494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2670494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2671494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2672494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2673494a190aSStefano Zampini   }
2674494a190aSStefano Zampini   if (!directionsprinted) {
2675494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2676494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2677494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2678494a190aSStefano Zampini   }
2679494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2680494a190aSStefano Zampini 
2681494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2682494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2683494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2684494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2685494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2686494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2687494a190aSStefano Zampini 
2688494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2689494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2690494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2691494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2692494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2693494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2694494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2695494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2696494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2697494a190aSStefano 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))));
2698494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2699494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2700494a190aSStefano Zampini 
2701494a190aSStefano Zampini   if (complete_print) {
2702494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2703494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2704494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2705494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2706494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2707494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2708494a190aSStefano Zampini   }
2709494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2710494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2711494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2712494a190aSStefano Zampini 
2713494a190aSStefano Zampini   if (complete_print) {
2714494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2715494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2716494a190aSStefano Zampini   }
2717494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2718494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2719494a190aSStefano Zampini }
2720494a190aSStefano Zampini 
2721d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2722d71ae5a4SJacob Faibussowitsch {
272312837594SBarry Smith   Mat               A, B, C, D, jacobian;
27244df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2725e885f1abSBarry Smith   PetscReal         nrm, gnorm;
272681e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27270e276705SLisandro Dalcin   MatType           mattype;
2728e885f1abSBarry Smith   PetscInt          m, n, M, N;
2729e885f1abSBarry Smith   void             *functx;
27302cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
27313325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2732e885f1abSBarry Smith   MPI_Comm          comm;
2733e885f1abSBarry Smith   PetscInt          tabs;
273412837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27353325ff46SBarry Smith   PetscViewerFormat format;
2736e885f1abSBarry Smith 
2737e885f1abSBarry Smith   PetscFunctionBegin;
2738d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
27409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27424ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27449566063dSJacob 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));
2745d0609cedSBarry Smith   PetscOptionsEnd();
27463ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2747e885f1abSBarry Smith 
27489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27499566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27509566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27519566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27529566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
275312837594SBarry Smith   if (!complete_print && !directionsprinted) {
27549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
275612837594SBarry Smith   }
275712837594SBarry Smith   if (!directionsprinted) {
27589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
27599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
276012837594SBarry Smith     directionsprinted = PETSC_TRUE;
2761e885f1abSBarry Smith   }
27621baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2763e885f1abSBarry Smith 
27649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
276512837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
276612837594SBarry Smith   else jacobian = snes->jacobian_pre;
276712837594SBarry Smith 
27684df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
27694df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
27709566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
27714df93895SStefano Zampini 
2772a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
27739566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
27749566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
27759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
277612837594SBarry Smith   while (jacobian) {
27772cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
27782cd624f9SStefano Zampini 
27792cd624f9SStefano Zampini     if (istranspose) {
27809566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
27812cd624f9SStefano Zampini       Jsave    = jacobian;
27822cd624f9SStefano Zampini       jacobian = JT;
27832cd624f9SStefano Zampini     }
27849566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
278512837594SBarry Smith     if (flg) {
278612837594SBarry Smith       A = jacobian;
27879566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
278812837594SBarry Smith     } else {
27899566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
279012837594SBarry Smith     }
2791e885f1abSBarry Smith 
27929566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
27939566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
27949566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
27959566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
27969566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
27979566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
27989566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
27999566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
28009566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2801e885f1abSBarry Smith 
28029566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28039566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
280412837594SBarry Smith 
28059566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28069566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28079566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28089566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28099566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
281012837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
28119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
281212837594SBarry Smith 
2813e885f1abSBarry Smith     if (complete_print) {
28149566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
28159566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
28169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
28179566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2818e885f1abSBarry Smith     }
2819e885f1abSBarry Smith 
2820df10fb39SFande Kong     if (threshold_print || complete_print) {
2821e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2822e885f1abSBarry Smith       PetscScalar       *cvals;
2823e885f1abSBarry Smith       const PetscInt    *bcols;
2824e885f1abSBarry Smith       const PetscScalar *bvals;
2825e885f1abSBarry Smith 
28269566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28279566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28289566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28299566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28309566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28319566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28320e276705SLisandro Dalcin 
28339566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28349566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2835e885f1abSBarry Smith 
2836e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28379566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28389566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2839e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
284023a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2841e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2842e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2843e885f1abSBarry Smith             cncols += 1;
2844e885f1abSBarry Smith           }
2845e885f1abSBarry Smith         }
284648a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28479566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28489566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2849e885f1abSBarry Smith       }
28509566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28519566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28539566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28549566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2855e885f1abSBarry Smith     }
28569566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
28579566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
28589566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
28592cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
286012837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
286112837594SBarry Smith       jacobian = snes->jacobian_pre;
28629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
28639371c9d4SSatish Balay     } else jacobian = NULL;
286412837594SBarry Smith   }
28659566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
28661baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2867648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
28689566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
28693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2870e885f1abSBarry Smith }
2871e885f1abSBarry Smith 
287262fef451SLois Curfman McInnes /*@
2873f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
287462fef451SLois Curfman McInnes 
2875c3339decSBarry Smith   Collective
2876c7afd0dbSLois Curfman McInnes 
287762fef451SLois Curfman McInnes   Input Parameters:
2878f6dfbefdSBarry Smith + snes - the `SNES` context
2879e4094ef1SJacob Faibussowitsch - X    - input vector
288062fef451SLois Curfman McInnes 
288162fef451SLois Curfman McInnes   Output Parameters:
2882c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2883420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2884fee21e36SBarry Smith 
2885e35cf81dSBarry Smith   Options Database Keys:
288667b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
288767b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2888455a5933SJed 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.
2889455a5933SJed 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
2890693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2891693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2892693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
28934c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
289494d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2895a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2896c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2897dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2898dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2899a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2900a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2901c01495d3SJed Brown 
2902dc4c0fb0SBarry Smith   Level: developer
2903dc4c0fb0SBarry Smith 
2904f6dfbefdSBarry Smith   Note:
290562fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
290662fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
290762fef451SLois Curfman McInnes 
2908420bcc1bSBarry Smith   Developer Note:
2909dc4c0fb0SBarry 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
2910420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2911e885f1abSBarry Smith 
29121cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
291362fef451SLois Curfman McInnes @*/
2914d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2915d71ae5a4SJacob Faibussowitsch {
2916ace3abfcSBarry Smith   PetscBool flag;
29176cab3a1bSJed Brown   DM        dm;
2918942e3340SBarry Smith   DMSNES    sdm;
2919e0e3a89bSBarry Smith   KSP       ksp;
29203a40ed3dSBarry Smith 
29213a40ed3dSBarry Smith   PetscFunctionBegin;
29220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29230700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2924c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2925e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29269566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29279566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29283232da50SPeter Brune 
292901c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2930fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2931fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2932f5af7f23SKarl Rupp 
29339566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2934fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29359566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29369566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2937ebd3b9afSBarry Smith     if (flag) {
29389566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29399566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2940ebd3b9afSBarry Smith     }
29413ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
294237ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
294363a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29449566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2945ebd3b9afSBarry Smith     if (flag) {
29469566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29479566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2948ebd3b9afSBarry Smith     }
29493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2950e35cf81dSBarry Smith   }
2951efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29529566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29539566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29543ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2955d728fb7dSPeter Brune   }
2956e35cf81dSBarry Smith 
29579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
29589566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2959800f99ffSJeremy L Thompson   {
2960800f99ffSJeremy L Thompson     void           *ctx;
29618434afd1SBarry Smith     SNESJacobianFn *J;
2962800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2963800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2964800f99ffSJeremy L Thompson   }
29659566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
29669566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
296728d58a37SPierre Jolivet 
296828d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
29699566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2970a8054027SBarry Smith 
2971e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
29729566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
29733b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
29749566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
29759566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
29763b4f5425SBarry Smith     snes->lagpreconditioner = -1;
29773b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
29789566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
29799566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
298037ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
298163a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
29829566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2983d1e9a80fSBarry Smith   } else {
29849566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
29859566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2986a8054027SBarry Smith   }
2987a8054027SBarry Smith 
29884df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
29894df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
29904df93895SStefano Zampini   {
29914df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
29924df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
29934df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
29944df93895SStefano Zampini 
29954df93895SStefano Zampini     snes->vec_sol      = X;
29964df93895SStefano Zampini     snes->jacobian     = A;
29974df93895SStefano Zampini     snes->jacobian_pre = B;
2998494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
29999566063dSJacob Faibussowitsch     PetscCall(SNESTestJacobian(snes));
3000494a190aSStefano Zampini 
30014df93895SStefano Zampini     snes->vec_sol      = xsave;
30024df93895SStefano Zampini     snes->jacobian     = jacobiansave;
30034df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
30044df93895SStefano Zampini   }
30054df93895SStefano Zampini 
3006693365a8SJed Brown   {
3007693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3008648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3009648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3010648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3011648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3012693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
30130298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
3014693365a8SJed Brown       PetscViewer vdraw, vstdout;
30156b3a5b13SJed Brown       PetscBool   flg;
3016693365a8SJed Brown       if (flag_operator) {
30179566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3018693365a8SJed Brown         Bexp = Bexp_mine;
3019693365a8SJed Brown       } else {
3020693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
30219566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
302294ab13aaSBarry Smith         if (flg) Bexp = B;
3023693365a8SJed Brown         else {
3024693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30259566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3026693365a8SJed Brown           Bexp = Bexp_mine;
3027693365a8SJed Brown         }
3028693365a8SJed Brown       }
30299566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30309566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3032693365a8SJed Brown       if (flag_draw || flag_contour) {
30339566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30349566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30350298fd71SBarry Smith       } else vdraw = NULL;
30369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30379566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30389566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30409566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30419566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30429566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30449566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3045693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30469566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30479566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30489566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3049693365a8SJed Brown       }
30509566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30519566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30529566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30539566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3054693365a8SJed Brown     }
3055693365a8SJed Brown   }
30564c30e9fbSJed Brown   {
30576719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
30586719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3059648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3060648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3061648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3062648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3063648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
306427b0f280SBarry Smith     if (flag_threshold) {
30659566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
30669566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
306727b0f280SBarry Smith     }
30686719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
30694c30e9fbSJed Brown       Mat             Bfd;
30704c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3071335efc43SPeter Brune       MatColoring     coloring;
30724c30e9fbSJed Brown       ISColoring      iscoloring;
30734c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
30748434afd1SBarry Smith       SNESFunctionFn *func;
30754c30e9fbSJed Brown       void           *funcctx;
30766719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
30774c30e9fbSJed Brown 
30789566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
30799566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
30809566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
30819566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
30829566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
30839566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
30849566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
30859566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30869566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
30879566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
30884c30e9fbSJed Brown 
30894c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
30909566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
30919566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))func, funcctx));
30929566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
30939566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
30949566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30959566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
30969566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
30974c30e9fbSJed Brown 
30989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
30994c30e9fbSJed Brown       if (flag_draw || flag_contour) {
31009566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31019566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31020298fd71SBarry Smith       } else vdraw = NULL;
31039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31049566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
31059566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
31069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31079566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31089566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
31099566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31109566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31119566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31129566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31149566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31154c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
31169566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31179566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
31189566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
31194c30e9fbSJed Brown       }
31209566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31216719d8e4SJed Brown 
31226719d8e4SJed Brown       if (flag_threshold) {
31236719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31249566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31259566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31266719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31276719d8e4SJed Brown           const PetscScalar *ba, *ca;
31286719d8e4SJed Brown           const PetscInt    *bj, *cj;
31296719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31306719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31319566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31329566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31335f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31346719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31356719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31366719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31376719d8e4SJed Brown               maxentrycol = bj[j];
31386719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31396719d8e4SJed Brown             }
31406719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31416719d8e4SJed Brown               maxdiffcol = bj[j];
31426719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31436719d8e4SJed Brown             }
31446719d8e4SJed Brown             if (rdiff > maxrdiff) {
31456719d8e4SJed Brown               maxrdiffcol = bj[j];
31466719d8e4SJed Brown               maxrdiff    = rdiff;
31476719d8e4SJed Brown             }
31486719d8e4SJed Brown           }
31496719d8e4SJed Brown           if (maxrdiff > 1) {
315063a3b9bcSJacob 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));
31516719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31526719d8e4SJed Brown               PetscReal rdiff;
31536719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
315448a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
31556719d8e4SJed Brown             }
315663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
31576719d8e4SJed Brown           }
31589566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
31599566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
31606719d8e4SJed Brown         }
31616719d8e4SJed Brown       }
31629566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
31639566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
31644c30e9fbSJed Brown     }
31654c30e9fbSJed Brown   }
31663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31679b94acceSBarry Smith }
31689b94acceSBarry Smith 
31699b94acceSBarry Smith /*@C
31709b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3171044dda88SLois Curfman McInnes   location to store the matrix.
31729b94acceSBarry Smith 
3173c3339decSBarry Smith   Logically Collective
3174c7afd0dbSLois Curfman McInnes 
31759b94acceSBarry Smith   Input Parameters:
3176f6dfbefdSBarry Smith + snes - the `SNES` context
3177e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3178dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
31798434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3180c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3181dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3182dc4c0fb0SBarry Smith 
3183dc4c0fb0SBarry Smith   Level: beginner
31849b94acceSBarry Smith 
31859b94acceSBarry Smith   Notes:
3186dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
318716913363SBarry Smith   each matrix.
318816913363SBarry Smith 
3189dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3190dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3191895c21f2SBarry Smith 
3192dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3193f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3194a8a26c1eSJed Brown 
3195c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3196f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3197c3cc8fd1SJed Brown 
31981cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
31998434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32009b94acceSBarry Smith @*/
32018434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3202d71ae5a4SJacob Faibussowitsch {
32036cab3a1bSJed Brown   DM dm;
32043a7fca6bSBarry Smith 
32053a40ed3dSBarry Smith   PetscFunctionBegin;
32060700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3207e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3208e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3209e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3210e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32119566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32129566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3213e5d3d808SBarry Smith   if (Amat) {
32149566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
32159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3216f5af7f23SKarl Rupp 
3217e5d3d808SBarry Smith     snes->jacobian = Amat;
32183a7fca6bSBarry Smith   }
3219e5d3d808SBarry Smith   if (Pmat) {
32209566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
32219566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3222f5af7f23SKarl Rupp 
3223e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32243a7fca6bSBarry Smith   }
32253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32269b94acceSBarry Smith }
322762fef451SLois Curfman McInnes 
3228c2aafc4cSSatish Balay /*@C
3229b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3230b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3231b4fd4287SBarry Smith 
3232420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3233c7afd0dbSLois Curfman McInnes 
3234b4fd4287SBarry Smith   Input Parameter:
3235b4fd4287SBarry Smith . snes - the nonlinear solver context
3236b4fd4287SBarry Smith 
3237b4fd4287SBarry Smith   Output Parameters:
3238dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3239dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32408434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3241dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3242fee21e36SBarry Smith 
324336851e7fSLois Curfman McInnes   Level: advanced
324436851e7fSLois Curfman McInnes 
32458434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3246b4fd4287SBarry Smith @*/
32478434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3248d71ae5a4SJacob Faibussowitsch {
32496cab3a1bSJed Brown   DM dm;
32506cab3a1bSJed Brown 
32513a40ed3dSBarry Smith   PetscFunctionBegin;
32520700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3253e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3254e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
32559566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3256800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
32573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3258b4fd4287SBarry Smith }
3259b4fd4287SBarry Smith 
3260d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3261d71ae5a4SJacob Faibussowitsch {
326258b371f3SBarry Smith   DM     dm;
326358b371f3SBarry Smith   DMSNES sdm;
326458b371f3SBarry Smith 
326558b371f3SBarry Smith   PetscFunctionBegin;
32669566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32679566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
326858b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
326958b371f3SBarry Smith     DM        dm;
327058b371f3SBarry Smith     PetscBool isdense, ismf;
327158b371f3SBarry Smith 
32729566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32739566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
32749566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
327558b371f3SBarry Smith     if (isdense) {
32769566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
327758b371f3SBarry Smith     } else if (!ismf) {
32789566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
327958b371f3SBarry Smith     }
328058b371f3SBarry Smith   }
32813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
328258b371f3SBarry Smith }
328358b371f3SBarry Smith 
32849b94acceSBarry Smith /*@
32859b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3286272ac6f2SLois Curfman McInnes   of a nonlinear solver.
32879b94acceSBarry Smith 
3288c3339decSBarry Smith   Collective
3289fee21e36SBarry Smith 
32902fe279fdSBarry Smith   Input Parameter:
3291f6dfbefdSBarry Smith . snes - the `SNES` context
3292c7afd0dbSLois Curfman McInnes 
3293dc4c0fb0SBarry Smith   Level: advanced
3294dc4c0fb0SBarry Smith 
3295f6dfbefdSBarry Smith   Note:
3296f6dfbefdSBarry Smith   For basic use of the `SNES` solvers the user need not explicitly call
3297f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3298f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3299f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3300f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3301272ac6f2SLois Curfman McInnes 
33021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`
33039b94acceSBarry Smith @*/
3304d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3305d71ae5a4SJacob Faibussowitsch {
33066cab3a1bSJed Brown   DM             dm;
3307942e3340SBarry Smith   DMSNES         sdm;
3308c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
33096e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
33109b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
33119b5c1c08SStefano Zampini   Vec            f, fpc;
33129b5c1c08SStefano Zampini   void          *funcctx;
33139b5c1c08SStefano Zampini   void          *jacctx, *appctx;
33149b5c1c08SStefano Zampini   Mat            j, jpre;
33156b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33166b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33178434afd1SBarry Smith   SNESFunctionFn *func;
33188434afd1SBarry Smith   SNESJacobianFn *jac;
33193a40ed3dSBarry Smith 
33203a40ed3dSBarry Smith   PetscFunctionBegin;
33210700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33223ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3323fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33249b94acceSBarry Smith 
332548a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
332685385478SLisandro Dalcin 
33279566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
332858c9b817SLisandro Dalcin 
33299566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33309566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33319566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
333258b371f3SBarry Smith 
333348a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3334efd51863SBarry Smith 
333548a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3336b710008aSBarry Smith 
3337d8d34be6SBarry Smith   if (snes->linesearch) {
33389566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33399566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3340d8d34be6SBarry Smith   }
33419e764e56SPeter Brune 
33429b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3343b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3344172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3345172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3346172a4300SPeter Brune   }
3347d8f46077SPeter Brune 
3348efd4aadfSBarry Smith   if (snes->npc) {
33496e2a1849SPeter Brune     /* copy the DM over */
33509566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33519566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33526e2a1849SPeter Brune 
33539566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33549566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
33559566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
33569566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
33579566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
33589566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
33599566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
33609b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
33619566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
33626e2a1849SPeter Brune 
33636e2a1849SPeter Brune     /* copy the function pointers over */
33649566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
33656e2a1849SPeter Brune 
33666e2a1849SPeter Brune     /* default to 1 iteration */
33679566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3368efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
33699566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3370a9936a0cSPeter Brune     } else {
33719566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3372a9936a0cSPeter Brune     }
33739566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
33746e2a1849SPeter Brune 
33756e2a1849SPeter Brune     /* copy the line search context over */
3376d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
33779566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
33789566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
33799566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
33809566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
33819566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
33829566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
33839566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
33846e2a1849SPeter Brune     }
3385d8d34be6SBarry Smith   }
33861baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
3387*49abdd8aSBarry Smith   if (snes->ops->usercompute && !snes->ctx) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->ctx));
33886e2a1849SPeter Brune 
338937ec4e1aSPeter Brune   snes->jac_iter = 0;
339037ec4e1aSPeter Brune   snes->pre_iter = 0;
339137ec4e1aSPeter Brune 
3392dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
339358c9b817SLisandro Dalcin 
33949566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
339558b371f3SBarry Smith 
3396b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
33976c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3398d8d34be6SBarry Smith       if (snes->linesearch) {
33999566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
34009566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34016c67d002SPeter Brune       }
34026c67d002SPeter Brune     }
3403d8d34be6SBarry Smith   }
3404fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34057aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
34063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34079b94acceSBarry Smith }
34089b94acceSBarry Smith 
340937596af1SLisandro Dalcin /*@
3410f6dfbefdSBarry Smith   SNESReset - Resets a `SNES` context to the snessetupcalled = 0 state and removes any allocated `Vec`s and `Mat`s
341137596af1SLisandro Dalcin 
3412c3339decSBarry Smith   Collective
341337596af1SLisandro Dalcin 
341437596af1SLisandro Dalcin   Input Parameter:
3415f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
341637596af1SLisandro Dalcin 
3417d25893d9SBarry Smith   Level: intermediate
3418d25893d9SBarry Smith 
341995452b02SPatrick Sanan   Notes:
3420f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
342137596af1SLisandro Dalcin 
3422f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3423f6dfbefdSBarry Smith 
34241cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
342537596af1SLisandro Dalcin @*/
3426d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3427d71ae5a4SJacob Faibussowitsch {
342837596af1SLisandro Dalcin   PetscFunctionBegin;
342937596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3430*49abdd8aSBarry Smith   if (snes->ops->ctxdestroy && snes->ctx) {
3431*49abdd8aSBarry Smith     PetscCallBack("SNES callback destroy application context", (*snes->ops->ctxdestroy)((void **)&snes->ctx));
3432*49abdd8aSBarry Smith     snes->ctx = NULL;
3433d25893d9SBarry Smith   }
34341baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34358a23116dSBarry Smith 
3436dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34371baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34389e764e56SPeter Brune 
34391baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34409e764e56SPeter Brune 
34419566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34429566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34439566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34449566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34459566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34469566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34479566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34489566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34499566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3450f5af7f23SKarl Rupp 
345140fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
345240fdac6aSLawrence Mitchell 
345337596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
345437596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
34553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
345637596af1SLisandro Dalcin }
345737596af1SLisandro Dalcin 
345852baeb72SSatish Balay /*@
345936d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
346036d43d94SBarry Smith   removes the default viewer.
3461c4421ceaSFande Kong 
3462c3339decSBarry Smith   Collective
3463c4421ceaSFande Kong 
3464c4421ceaSFande Kong   Input Parameter:
3465f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
3466c4421ceaSFande Kong 
3467c4421ceaSFande Kong   Level: intermediate
3468c4421ceaSFande Kong 
3469420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3470c4421ceaSFande Kong @*/
3471d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3472d71ae5a4SJacob Faibussowitsch {
3473c4421ceaSFande Kong   PetscInt i;
3474c4421ceaSFande Kong 
3475c4421ceaSFande Kong   PetscFunctionBegin;
3476c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3477c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
347848a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3479c4421ceaSFande Kong   }
3480c4421ceaSFande Kong   snes->numberreasonviews = 0;
3481648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
34823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3483c4421ceaSFande Kong }
3484c4421ceaSFande Kong 
34850764c050SBarry Smith /*@
34869b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3487f6dfbefdSBarry Smith   with `SNESCreate()`.
34889b94acceSBarry Smith 
3489c3339decSBarry Smith   Collective
3490c7afd0dbSLois Curfman McInnes 
34919b94acceSBarry Smith   Input Parameter:
3492f6dfbefdSBarry Smith . snes - the `SNES` context
34939b94acceSBarry Smith 
349436851e7fSLois Curfman McInnes   Level: beginner
349536851e7fSLois Curfman McInnes 
34961cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
34979b94acceSBarry Smith @*/
3498d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3499d71ae5a4SJacob Faibussowitsch {
35003a40ed3dSBarry Smith   PetscFunctionBegin;
35013ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3502f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3503f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
35049371c9d4SSatish Balay     *snes = NULL;
35053ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
35069371c9d4SSatish Balay   }
3507d4bb536fSBarry Smith 
3508f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
35099566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
35106b8b9a38SLisandro Dalcin 
3511e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
35129566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3513f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
35146d4c513bSLisandro Dalcin 
35159566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
35169566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
35179566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
35189566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35196b8b9a38SLisandro Dalcin 
35209566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
352148a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
352248a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3523f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3524f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35259566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35279b94acceSBarry Smith }
35289b94acceSBarry Smith 
35299b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35309b94acceSBarry Smith 
3531a8054027SBarry Smith /*@
3532a8054027SBarry Smith   SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve.
3533a8054027SBarry Smith 
3534c3339decSBarry Smith   Logically Collective
3535a8054027SBarry Smith 
3536a8054027SBarry Smith   Input Parameters:
3537f6dfbefdSBarry Smith + snes - the `SNES` context
3538d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35393b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3540a8054027SBarry Smith 
3541a8054027SBarry Smith   Options Database Keys:
3542420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35433d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3544420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35453d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3546a8054027SBarry Smith 
3547dc4c0fb0SBarry Smith   Level: intermediate
3548dc4c0fb0SBarry Smith 
3549420bcc1bSBarry Smith   Notes:
3550a8054027SBarry Smith   The default is 1
3551420bcc1bSBarry Smith 
3552f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3553d8e291bfSBarry Smith 
3554f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3555a8054027SBarry Smith 
35563201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3557f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3558a8054027SBarry Smith @*/
3559d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3560d71ae5a4SJacob Faibussowitsch {
3561a8054027SBarry Smith   PetscFunctionBegin;
35620700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35635f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35645f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3565c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3566a8054027SBarry Smith   snes->lagpreconditioner = lag;
35673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3568a8054027SBarry Smith }
3569a8054027SBarry Smith 
3570efd51863SBarry Smith /*@
3571f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3572efd51863SBarry Smith 
3573c3339decSBarry Smith   Logically Collective
3574efd51863SBarry Smith 
3575efd51863SBarry Smith   Input Parameters:
3576f6dfbefdSBarry Smith + snes  - the `SNES` context
3577efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3578efd51863SBarry Smith 
3579f6dfbefdSBarry Smith   Options Database Key:
358067b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3581efd51863SBarry Smith 
3582efd51863SBarry Smith   Level: intermediate
3583efd51863SBarry Smith 
3584f6dfbefdSBarry Smith   Note:
3585f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3586c0df2a02SJed Brown 
35873201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
3588420bcc1bSBarry Smith           `SNESetDM()`
3589efd51863SBarry Smith @*/
3590d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3591d71ae5a4SJacob Faibussowitsch {
3592efd51863SBarry Smith   PetscFunctionBegin;
3593efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3594efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3595efd51863SBarry Smith   snes->gridsequence = steps;
35963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3597efd51863SBarry Smith }
3598efd51863SBarry Smith 
3599fa19ca70SBarry Smith /*@
3600f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3601fa19ca70SBarry Smith 
3602c3339decSBarry Smith   Logically Collective
3603fa19ca70SBarry Smith 
3604fa19ca70SBarry Smith   Input Parameter:
3605f6dfbefdSBarry Smith . snes - the `SNES` context
3606fa19ca70SBarry Smith 
3607fa19ca70SBarry Smith   Output Parameter:
3608fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3609fa19ca70SBarry Smith 
3610fa19ca70SBarry Smith   Level: intermediate
3611fa19ca70SBarry Smith 
36123201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3613fa19ca70SBarry Smith @*/
3614d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3615d71ae5a4SJacob Faibussowitsch {
3616fa19ca70SBarry Smith   PetscFunctionBegin;
3617fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3618fa19ca70SBarry Smith   *steps = snes->gridsequence;
36193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3620fa19ca70SBarry Smith }
3621fa19ca70SBarry Smith 
3622a8054027SBarry Smith /*@
3623f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3624a8054027SBarry Smith 
36253f9fe445SBarry Smith   Not Collective
3626a8054027SBarry Smith 
3627a8054027SBarry Smith   Input Parameter:
3628f6dfbefdSBarry Smith . snes - the `SNES` context
3629a8054027SBarry Smith 
3630a8054027SBarry Smith   Output Parameter:
3631a8054027SBarry 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
36323b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3633a8054027SBarry Smith 
3634dc4c0fb0SBarry Smith   Level: intermediate
3635dc4c0fb0SBarry Smith 
3636a8054027SBarry Smith   Notes:
3637a8054027SBarry Smith   The default is 1
3638f6dfbefdSBarry Smith 
3639a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3640a8054027SBarry Smith 
36413201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3642a8054027SBarry Smith @*/
3643d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3644d71ae5a4SJacob Faibussowitsch {
3645a8054027SBarry Smith   PetscFunctionBegin;
36460700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3647a8054027SBarry Smith   *lag = snes->lagpreconditioner;
36483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3649a8054027SBarry Smith }
3650a8054027SBarry Smith 
3651e35cf81dSBarry Smith /*@
3652f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3653e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3654e35cf81dSBarry Smith 
3655c3339decSBarry Smith   Logically Collective
3656e35cf81dSBarry Smith 
3657e35cf81dSBarry Smith   Input Parameters:
3658f6dfbefdSBarry Smith + snes - the `SNES` context
3659e35cf81dSBarry 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
3660fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3661e35cf81dSBarry Smith 
3662e35cf81dSBarry Smith   Options Database Keys:
366379a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36643d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
366579a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36663d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3667e35cf81dSBarry Smith 
3668dc4c0fb0SBarry Smith   Level: intermediate
3669dc4c0fb0SBarry Smith 
3670e35cf81dSBarry Smith   Notes:
3671e35cf81dSBarry Smith   The default is 1
3672f6dfbefdSBarry Smith 
3673e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3674f6dfbefdSBarry Smith 
3675fe3ffe1eSBarry 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
3676fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3677e35cf81dSBarry Smith 
36783201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3679e35cf81dSBarry Smith @*/
3680d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3681d71ae5a4SJacob Faibussowitsch {
3682e35cf81dSBarry Smith   PetscFunctionBegin;
36830700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36845f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36855f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3686c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3687e35cf81dSBarry Smith   snes->lagjacobian = lag;
36883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3689e35cf81dSBarry Smith }
3690e35cf81dSBarry Smith 
3691e35cf81dSBarry Smith /*@
3692f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3693e35cf81dSBarry Smith 
36943f9fe445SBarry Smith   Not Collective
3695e35cf81dSBarry Smith 
3696e35cf81dSBarry Smith   Input Parameter:
3697f6dfbefdSBarry Smith . snes - the `SNES` context
3698e35cf81dSBarry Smith 
3699e35cf81dSBarry Smith   Output Parameter:
3700e35cf81dSBarry 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
3701e35cf81dSBarry Smith          the Jacobian is built etc.
3702e35cf81dSBarry Smith 
3703dc4c0fb0SBarry Smith   Level: intermediate
3704dc4c0fb0SBarry Smith 
3705e35cf81dSBarry Smith   Notes:
3706e35cf81dSBarry Smith   The default is 1
3707f6dfbefdSBarry Smith 
3708f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3709e35cf81dSBarry Smith 
37103201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3711e35cf81dSBarry Smith 
3712e35cf81dSBarry Smith @*/
3713d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3714d71ae5a4SJacob Faibussowitsch {
3715e35cf81dSBarry Smith   PetscFunctionBegin;
37160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3717e35cf81dSBarry Smith   *lag = snes->lagjacobian;
37183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3719e35cf81dSBarry Smith }
3720e35cf81dSBarry Smith 
372137ec4e1aSPeter Brune /*@
3722f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
372337ec4e1aSPeter Brune 
3724c3339decSBarry Smith   Logically collective
372537ec4e1aSPeter Brune 
3726d8d19677SJose E. Roman   Input Parameters:
3727f6dfbefdSBarry Smith + snes - the `SNES` context
37289d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
372937ec4e1aSPeter Brune 
373037ec4e1aSPeter Brune   Options Database Keys:
373179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37323d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
373379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37343d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37353d5a8a6aSBarry Smith 
3736dc4c0fb0SBarry Smith   Level: advanced
3737dc4c0fb0SBarry Smith 
373895452b02SPatrick Sanan   Notes:
3739420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3740f6dfbefdSBarry Smith 
374195452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
374237ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
374337ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
374437ec4e1aSPeter Brune 
374542747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
374637ec4e1aSPeter Brune @*/
3747d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3748d71ae5a4SJacob Faibussowitsch {
374937ec4e1aSPeter Brune   PetscFunctionBegin;
375037ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
375137ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
375237ec4e1aSPeter Brune   snes->lagjac_persist = flg;
37533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
375437ec4e1aSPeter Brune }
375537ec4e1aSPeter Brune 
375637ec4e1aSPeter Brune /*@
3757d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
375837ec4e1aSPeter Brune 
3759c3339decSBarry Smith   Logically Collective
376037ec4e1aSPeter Brune 
3761d8d19677SJose E. Roman   Input Parameters:
3762f6dfbefdSBarry Smith + snes - the `SNES` context
37639d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
376437ec4e1aSPeter Brune 
376537ec4e1aSPeter Brune   Options Database Keys:
376679a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37673d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
376879a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37693d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
377037ec4e1aSPeter Brune 
3771dc4c0fb0SBarry Smith   Level: developer
3772dc4c0fb0SBarry Smith 
377395452b02SPatrick Sanan   Notes:
3774420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3775f6dfbefdSBarry Smith 
377695452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
377737ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
377837ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
377937ec4e1aSPeter Brune 
37801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
378137ec4e1aSPeter Brune @*/
3782d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3783d71ae5a4SJacob Faibussowitsch {
378437ec4e1aSPeter Brune   PetscFunctionBegin;
378537ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
378637ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
378737ec4e1aSPeter Brune   snes->lagpre_persist = flg;
37883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
378937ec4e1aSPeter Brune }
379037ec4e1aSPeter Brune 
37919b94acceSBarry Smith /*@
3792f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3793be5caee7SBarry Smith 
3794c3339decSBarry Smith   Logically Collective
3795be5caee7SBarry Smith 
3796be5caee7SBarry Smith   Input Parameters:
3797f6dfbefdSBarry Smith + snes  - the `SNES` context
3798f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3799be5caee7SBarry Smith 
3800f6dfbefdSBarry Smith   Options Database Key:
3801be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3802be5caee7SBarry Smith 
3803dc4c0fb0SBarry Smith   Level: intermediate
3804dc4c0fb0SBarry Smith 
3805f6dfbefdSBarry Smith   Note:
3806f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3807be5caee7SBarry Smith 
38083201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3809be5caee7SBarry Smith @*/
3810d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3811d71ae5a4SJacob Faibussowitsch {
3812be5caee7SBarry Smith   PetscFunctionBegin;
3813be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3814be5caee7SBarry Smith   snes->forceiteration = force;
38153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3816be5caee7SBarry Smith }
3817be5caee7SBarry Smith 
381885216dc7SFande Kong /*@
3819f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
382085216dc7SFande Kong 
3821c3339decSBarry Smith   Logically Collective
382285216dc7SFande Kong 
38232fe279fdSBarry Smith   Input Parameter:
3824f6dfbefdSBarry Smith . snes - the `SNES` context
382585216dc7SFande Kong 
382685216dc7SFande Kong   Output Parameter:
3827dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
382885216dc7SFande Kong 
382906dd6b0eSSatish Balay   Level: intermediate
383006dd6b0eSSatish Balay 
38313201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
383285216dc7SFande Kong @*/
3833d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3834d71ae5a4SJacob Faibussowitsch {
383585216dc7SFande Kong   PetscFunctionBegin;
383685216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
383785216dc7SFande Kong   *force = snes->forceiteration;
38383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
383985216dc7SFande Kong }
3840be5caee7SBarry Smith 
3841be5caee7SBarry Smith /*@
3842f6dfbefdSBarry Smith   SNESSetTolerances - Sets `SNES` various parameters used in convergence tests.
38439b94acceSBarry Smith 
3844c3339decSBarry Smith   Logically Collective
3845c7afd0dbSLois Curfman McInnes 
38469b94acceSBarry Smith   Input Parameters:
3847f6dfbefdSBarry Smith + snes   - the `SNES` context
384870441072SBarry Smith . abstol - absolute convergence tolerance
384933174efeSLois Curfman McInnes . rtol   - relative convergence tolerance
38505358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3851f6dfbefdSBarry Smith . maxit  - maximum number of iterations, default 50.
385277e5a1f9SBarry Smith - maxf   - maximum number of function evaluations (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3853fee21e36SBarry Smith 
385433174efeSLois Curfman McInnes   Options Database Keys:
385577e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
385677e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
385777e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
385877e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
385977e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
38609b94acceSBarry Smith 
386136851e7fSLois Curfman McInnes   Level: intermediate
386236851e7fSLois Curfman McInnes 
386377e5a1f9SBarry Smith   Note:
386477e5a1f9SBarry Smith   All parameters must be non-negative
386577e5a1f9SBarry Smith 
386677e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
386777e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
386877e5a1f9SBarry Smith 
386977e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
387077e5a1f9SBarry Smith 
387177e5a1f9SBarry Smith   Fortran Note:
387277e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
387377e5a1f9SBarry Smith 
38743201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
38759b94acceSBarry Smith @*/
3876d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3877d71ae5a4SJacob Faibussowitsch {
38783a40ed3dSBarry Smith   PetscFunctionBegin;
38790700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3880c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3881c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3882c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3883c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3884c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3885c5eb9154SBarry Smith 
388677e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
388777e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
388877e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
38895f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3890ab54825eSJed Brown     snes->abstol = abstol;
3891ab54825eSJed Brown   }
389277e5a1f9SBarry Smith 
389377e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
389477e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
389577e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
38965f80ce2aSJacob 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);
3897ab54825eSJed Brown     snes->rtol = rtol;
3898ab54825eSJed Brown   }
389977e5a1f9SBarry Smith 
390077e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
390177e5a1f9SBarry Smith     snes->stol = snes->default_stol;
390277e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
39035f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3904c60f73f4SPeter Brune     snes->stol = stol;
3905ab54825eSJed Brown   }
390677e5a1f9SBarry Smith 
390777e5a1f9SBarry Smith   if (maxit == (PetscInt)PETSC_DETERMINE) {
390877e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
390977e5a1f9SBarry Smith   } else if (maxit == (PetscInt)PETSC_UNLIMITED) {
391077e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
391177e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
391263a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3913ab54825eSJed Brown     snes->max_its = maxit;
3914ab54825eSJed Brown   }
391577e5a1f9SBarry Smith 
391677e5a1f9SBarry Smith   if (maxf == (PetscInt)PETSC_DETERMINE) {
391777e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
391877e5a1f9SBarry Smith   } else if (maxf == (PetscInt)PETSC_UNLIMITED || maxf == -1) {
391977e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
392077e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
392177e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3922ab54825eSJed Brown     snes->max_funcs = maxf;
3923ab54825eSJed Brown   }
39243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39259b94acceSBarry Smith }
39269b94acceSBarry Smith 
3927e4d06f11SPatrick Farrell /*@
3928f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3929e4d06f11SPatrick Farrell 
3930c3339decSBarry Smith   Logically Collective
3931e4d06f11SPatrick Farrell 
3932e4d06f11SPatrick Farrell   Input Parameters:
3933f6dfbefdSBarry Smith + snes   - the `SNES` context
39343201ab8dSStefano Zampini - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test.
3935e4d06f11SPatrick Farrell 
3936f6dfbefdSBarry Smith   Options Database Key:
3937dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3938e4d06f11SPatrick Farrell 
3939e4d06f11SPatrick Farrell   Level: intermediate
3940e4d06f11SPatrick Farrell 
394177e5a1f9SBarry Smith   Notes:
394277e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
3943e5cd489fSStefano Zampini 
394477e5a1f9SBarry Smith   Fortran Note:
394577e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
394677e5a1f9SBarry Smith 
394777e5a1f9SBarry Smith   Developer Note:
394877e5a1f9SBarry Smith   Also supports the deprecated -1 to indicate no bound on the growth of the residual
394977e5a1f9SBarry Smith 
395077e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
3951e4d06f11SPatrick Farrell @*/
3952d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3953d71ae5a4SJacob Faibussowitsch {
3954e4d06f11SPatrick Farrell   PetscFunctionBegin;
3955e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3956e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
395777e5a1f9SBarry Smith 
395877e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
395977e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
396077e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
396177e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
396277e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
396377e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
396477e5a1f9SBarry Smith     snes->divtol = divtol;
396577e5a1f9SBarry Smith   }
39663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3967e4d06f11SPatrick Farrell }
3968e4d06f11SPatrick Farrell 
39699b94acceSBarry Smith /*@
397033174efeSLois Curfman McInnes   SNESGetTolerances - Gets various parameters used in convergence tests.
397133174efeSLois Curfman McInnes 
3972c7afd0dbSLois Curfman McInnes   Not Collective
3973c7afd0dbSLois Curfman McInnes 
397477e5a1f9SBarry Smith   Input Parameter:
397577e5a1f9SBarry Smith . snes - the `SNES` context
397677e5a1f9SBarry Smith 
397777e5a1f9SBarry Smith   Output Parameters:
397877e5a1f9SBarry Smith + atol  - absolute convergence tolerance
397933174efeSLois Curfman McInnes . rtol  - relative convergence tolerance
398077e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
398133174efeSLois Curfman McInnes . maxit - maximum number of iterations
398277e5a1f9SBarry Smith - maxf  - maximum number of function evaluations, `PETSC_UNLIMITED` indicates no bound
3983fee21e36SBarry Smith 
398436851e7fSLois Curfman McInnes   Level: intermediate
398536851e7fSLois Curfman McInnes 
3986dc4c0fb0SBarry Smith   Note:
3987dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3988dc4c0fb0SBarry Smith 
39891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
399033174efeSLois Curfman McInnes @*/
3991d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
3992d71ae5a4SJacob Faibussowitsch {
39933a40ed3dSBarry Smith   PetscFunctionBegin;
39940700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
399585385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
399633174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
3997c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
399833174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
399933174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
40003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
400133174efeSLois Curfman McInnes }
400233174efeSLois Curfman McInnes 
4003e4d06f11SPatrick Farrell /*@
4004e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4005e4d06f11SPatrick Farrell 
4006e4d06f11SPatrick Farrell   Not Collective
4007e4d06f11SPatrick Farrell 
4008e4d06f11SPatrick Farrell   Input Parameters:
4009f6dfbefdSBarry Smith + snes   - the `SNES` context
4010e4d06f11SPatrick Farrell - divtol - divergence tolerance
4011e4d06f11SPatrick Farrell 
4012e4d06f11SPatrick Farrell   Level: intermediate
4013e4d06f11SPatrick Farrell 
40141cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4015e4d06f11SPatrick Farrell @*/
4016d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4017d71ae5a4SJacob Faibussowitsch {
4018e4d06f11SPatrick Farrell   PetscFunctionBegin;
4019e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4020e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
40213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4022e4d06f11SPatrick Farrell }
4023e4d06f11SPatrick Farrell 
40246ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40256ba87a44SLisandro Dalcin 
4026d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4027d71ae5a4SJacob Faibussowitsch {
4028b271bb04SBarry Smith   PetscDrawLG      lg;
4029b271bb04SBarry Smith   PetscReal        x, y, per;
4030b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4031b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4032b271bb04SBarry Smith   PetscDraw        draw;
4033b271bb04SBarry Smith 
4034459f5d12SBarry Smith   PetscFunctionBegin;
40354d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40369566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40379566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40389566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40399566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4040b271bb04SBarry Smith   x = (PetscReal)n;
404177b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
404294c9c6d3SKarl Rupp   else y = -15.0;
40439566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40446934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40459566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40469566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4047b271bb04SBarry Smith   }
4048b271bb04SBarry Smith 
40499566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
40509566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40519566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4052aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
40539566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4054b271bb04SBarry Smith   x = (PetscReal)n;
4055b271bb04SBarry Smith   y = 100.0 * per;
40569566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40576934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40589566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40599566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4060b271bb04SBarry Smith   }
4061b271bb04SBarry Smith 
40629566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
40639371c9d4SSatish Balay   if (!n) {
40649371c9d4SSatish Balay     prev = rnorm;
40659371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
40669371c9d4SSatish Balay   }
40679566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40689566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4069b271bb04SBarry Smith   x = (PetscReal)n;
4070b271bb04SBarry Smith   y = (prev - rnorm) / prev;
40719566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40726934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40739566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40749566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4075b271bb04SBarry Smith   }
4076b271bb04SBarry Smith 
40779566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
40789566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40799566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40809566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4081b271bb04SBarry Smith   x = (PetscReal)n;
4082b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4083b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
40849566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4085b271bb04SBarry Smith   }
40866934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40879566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40889566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4089b271bb04SBarry Smith   }
4090b271bb04SBarry Smith   prev = rnorm;
40913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4092b271bb04SBarry Smith }
4093b271bb04SBarry Smith 
4094228d79bcSJed Brown /*@
40952d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
40962d157150SStefano Zampini 
40972d157150SStefano Zampini   Collective
40982d157150SStefano Zampini 
40992d157150SStefano Zampini   Input Parameters:
41002d157150SStefano Zampini + snes  - the `SNES` context
41012d157150SStefano Zampini . it    - current iteration
41022d157150SStefano Zampini . xnorm - 2-norm of current iterate
41032d157150SStefano Zampini . snorm - 2-norm of current step
41042d157150SStefano Zampini - fnorm - 2-norm of function
41052d157150SStefano Zampini 
41062d157150SStefano Zampini   Level: developer
41072d157150SStefano Zampini 
41082d157150SStefano Zampini   Note:
4109420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41102d157150SStefano Zampini   It does not typically need to be called by the user.
41112d157150SStefano Zampini 
4112be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
41132d157150SStefano Zampini @*/
41142d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41152d157150SStefano Zampini {
41162d157150SStefano Zampini   PetscFunctionBegin;
41172d157150SStefano Zampini   if (!snes->reason) {
41182d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41192d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41202d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41212d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41222d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41232d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41242d157150SStefano Zampini     }
41252d157150SStefano Zampini   }
41262d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41272d157150SStefano Zampini }
41282d157150SStefano Zampini 
41292d157150SStefano Zampini /*@
4130228d79bcSJed Brown   SNESMonitor - runs the user provided monitor routines, if they exist
4131228d79bcSJed Brown 
4132c3339decSBarry Smith   Collective
4133228d79bcSJed Brown 
4134228d79bcSJed Brown   Input Parameters:
4135f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
4136228d79bcSJed Brown . iter  - iteration number
4137228d79bcSJed Brown - rnorm - relative norm of the residual
4138228d79bcSJed Brown 
4139dc4c0fb0SBarry Smith   Level: developer
4140dc4c0fb0SBarry Smith 
4141f6dfbefdSBarry Smith   Note:
4142420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4143228d79bcSJed Brown   It does not typically need to be called by the user.
4144228d79bcSJed Brown 
41451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4146228d79bcSJed Brown @*/
4147d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4148d71ae5a4SJacob Faibussowitsch {
41497a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
41507a03ce2fSLisandro Dalcin 
41517a03ce2fSLisandro Dalcin   PetscFunctionBegin;
41525f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
41539566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
415448a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
41559566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
41563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41577a03ce2fSLisandro Dalcin }
41587a03ce2fSLisandro Dalcin 
41599b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
41609b94acceSBarry Smith 
4161bf388a1fSBarry Smith /*MC
4162f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4163bf388a1fSBarry Smith 
4164bf388a1fSBarry Smith      Synopsis:
4165aaa7dc30SBarry Smith      #include <petscsnes.h>
416637fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4167bf388a1fSBarry Smith 
4168c3339decSBarry Smith      Collective
41691843f636SBarry Smith 
41701843f636SBarry Smith     Input Parameters:
4171f6dfbefdSBarry Smith +    snes - the `SNES` context
4172bf388a1fSBarry Smith .    its - iteration number
4173bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4174bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4175bf388a1fSBarry Smith 
4176878cb397SSatish Balay    Level: advanced
4177878cb397SSatish Balay 
41781cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4179bf388a1fSBarry Smith M*/
4180bf388a1fSBarry Smith 
41819b94acceSBarry Smith /*@C
4182a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
41839b94acceSBarry Smith   iteration of the nonlinear solver to display the iteration's
41849b94acceSBarry Smith   progress.
41859b94acceSBarry Smith 
4186c3339decSBarry Smith   Logically Collective
4187fee21e36SBarry Smith 
4188c7afd0dbSLois Curfman McInnes   Input Parameters:
4189f6dfbefdSBarry Smith + snes           - the `SNES` context
419020f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4191420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4192*49abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
41939b94acceSBarry Smith 
41949665c990SLois Curfman McInnes   Options Database Keys:
4195f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4196798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4197dc4c0fb0SBarry 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
4198c7afd0dbSLois Curfman McInnes                                 the options database.
41999665c990SLois Curfman McInnes 
4200dc4c0fb0SBarry Smith   Level: intermediate
4201dc4c0fb0SBarry Smith 
4202f6dfbefdSBarry Smith   Note:
42036bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4204f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42056bc08f3fSLois Curfman McInnes   order in which they were set.
4206639f9d9dSBarry Smith 
4207420bcc1bSBarry Smith   Fortran Note:
4208f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4209025f1a04SBarry Smith 
4210*49abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`, `PetscCtxDestroyFn`
42119b94acceSBarry Smith @*/
4212*49abdd8aSBarry Smith PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
4213d71ae5a4SJacob Faibussowitsch {
4214b90d0a6eSBarry Smith   PetscInt  i;
421578064530SBarry Smith   PetscBool identical;
4216b90d0a6eSBarry Smith 
42173a40ed3dSBarry Smith   PetscFunctionBegin;
42180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4219b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
42209566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42213ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4222649052a6SBarry Smith   }
42235f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42246e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4225b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4226639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
42273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42289b94acceSBarry Smith }
42299b94acceSBarry Smith 
4230a278d85bSSatish Balay /*@
4231f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42325cd90555SBarry Smith 
4233c3339decSBarry Smith   Logically Collective
4234c7afd0dbSLois Curfman McInnes 
42352fe279fdSBarry Smith   Input Parameter:
4236f6dfbefdSBarry Smith . snes - the `SNES` context
42375cd90555SBarry Smith 
42381a480d89SAdministrator   Options Database Key:
4239a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4240dc4c0fb0SBarry Smith     into a code by calls to `SNESMonitorSet()`, but does not cancel those
4241c7afd0dbSLois Curfman McInnes     set via the options database
42425cd90555SBarry Smith 
4243dc4c0fb0SBarry Smith   Level: intermediate
4244dc4c0fb0SBarry Smith 
4245f6dfbefdSBarry Smith   Note:
4246f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
42475cd90555SBarry Smith 
42481cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
42495cd90555SBarry Smith @*/
4250d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4251d71ae5a4SJacob Faibussowitsch {
4252d952e501SBarry Smith   PetscInt i;
4253d952e501SBarry Smith 
42545cd90555SBarry Smith   PetscFunctionBegin;
42550700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4256d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
425748a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4258d952e501SBarry Smith   }
42595cd90555SBarry Smith   snes->numbermonitors = 0;
42603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42615cd90555SBarry Smith }
42625cd90555SBarry Smith 
4263bf388a1fSBarry Smith /*MC
4264bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4265bf388a1fSBarry Smith 
4266bf388a1fSBarry Smith      Synopsis:
4267aaa7dc30SBarry Smith      #include <petscsnes.h>
426837fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4269bf388a1fSBarry Smith 
4270c3339decSBarry Smith      Collective
42711843f636SBarry Smith 
42721843f636SBarry Smith     Input Parameters:
4273f6dfbefdSBarry Smith +    snes - the `SNES` context
4274bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4275bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4276bf388a1fSBarry Smith .    gnorm - 2-norm of current step
42771843f636SBarry Smith .    f - 2-norm of function
42781843f636SBarry Smith -    cctx - [optional] convergence context
42791843f636SBarry Smith 
42801843f636SBarry Smith     Output Parameter:
42811843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4282bf388a1fSBarry Smith 
4283878cb397SSatish Balay    Level: intermediate
4284bf388a1fSBarry Smith 
42851cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4286bf388a1fSBarry Smith M*/
4287bf388a1fSBarry Smith 
42889b94acceSBarry Smith /*@C
42899b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
42909b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
42919b94acceSBarry Smith 
4292c3339decSBarry Smith   Logically Collective
4293fee21e36SBarry Smith 
4294c7afd0dbSLois Curfman McInnes   Input Parameters:
4295f6dfbefdSBarry Smith + snes                        - the `SNES` context
4296e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4297dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4298dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
42999b94acceSBarry Smith 
430036851e7fSLois Curfman McInnes   Level: advanced
430136851e7fSLois Curfman McInnes 
43021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43039b94acceSBarry Smith @*/
4304d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4305d71ae5a4SJacob Faibussowitsch {
43063a40ed3dSBarry Smith   PetscFunctionBegin;
43070700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4308e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
43091baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4310bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43117f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
431285385478SLisandro Dalcin   snes->cnvP                  = cctx;
43133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43149b94acceSBarry Smith }
43159b94acceSBarry Smith 
431652baeb72SSatish Balay /*@
4317f6dfbefdSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped.
4318184914b5SBarry Smith 
4319184914b5SBarry Smith   Not Collective
4320184914b5SBarry Smith 
4321184914b5SBarry Smith   Input Parameter:
4322f6dfbefdSBarry Smith . snes - the `SNES` context
4323184914b5SBarry Smith 
4324184914b5SBarry Smith   Output Parameter:
4325f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4326184914b5SBarry Smith 
4327f6dfbefdSBarry Smith   Options Database Key:
43286a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43296a4d7782SBarry Smith 
4330184914b5SBarry Smith   Level: intermediate
4331184914b5SBarry Smith 
4332f6dfbefdSBarry Smith   Note:
4333f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4334184914b5SBarry Smith 
43351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4336184914b5SBarry Smith @*/
4337d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4338d71ae5a4SJacob Faibussowitsch {
4339184914b5SBarry Smith   PetscFunctionBegin;
43400700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43414f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4342184914b5SBarry Smith   *reason = snes->reason;
43433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4344184914b5SBarry Smith }
4345184914b5SBarry Smith 
4346c4421ceaSFande Kong /*@C
4347f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4348c4421ceaSFande Kong 
4349c4421ceaSFande Kong   Not Collective
4350c4421ceaSFande Kong 
4351c4421ceaSFande Kong   Input Parameter:
4352f6dfbefdSBarry Smith . snes - the `SNES` context
4353c4421ceaSFande Kong 
4354c4421ceaSFande Kong   Output Parameter:
4355dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4356c4421ceaSFande Kong 
435799c90e12SSatish Balay   Level: beginner
4358c4421ceaSFande Kong 
43591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4360c4421ceaSFande Kong @*/
4361d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4362d71ae5a4SJacob Faibussowitsch {
4363c4421ceaSFande Kong   PetscFunctionBegin;
4364c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43654f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4366c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
43673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4368c4421ceaSFande Kong }
4369c4421ceaSFande Kong 
437033866048SMatthew G. Knepley /*@
4371f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
437233866048SMatthew G. Knepley 
437333866048SMatthew G. Knepley   Not Collective
437433866048SMatthew G. Knepley 
437533866048SMatthew G. Knepley   Input Parameters:
4376f6dfbefdSBarry Smith + snes   - the `SNES` context
4377f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
437833866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
437933866048SMatthew G. Knepley 
4380f6dfbefdSBarry Smith   Level: developer
4381f6dfbefdSBarry Smith 
4382420bcc1bSBarry Smith   Developer Note:
4383f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
438433866048SMatthew G. Knepley 
43851cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
438633866048SMatthew G. Knepley @*/
4387d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4388d71ae5a4SJacob Faibussowitsch {
438933866048SMatthew G. Knepley   PetscFunctionBegin;
439033866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43915f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
439233866048SMatthew G. Knepley   snes->reason = reason;
43933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
439433866048SMatthew G. Knepley }
439533866048SMatthew G. Knepley 
4396c9005455SLois Curfman McInnes /*@
4397420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4398c9005455SLois Curfman McInnes 
4399c3339decSBarry Smith   Logically Collective
4400fee21e36SBarry Smith 
4401c7afd0dbSLois Curfman McInnes   Input Parameters:
4402f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44038c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4404cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4405420bcc1bSBarry Smith . na    - size of `a` and `its`
4406f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4407758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4408c7afd0dbSLois Curfman McInnes 
4409dc4c0fb0SBarry Smith   Level: intermediate
4410dc4c0fb0SBarry Smith 
4411308dcc3eSBarry Smith   Notes:
441277e5a1f9SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` then a
441377e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4414308dcc3eSBarry Smith 
4415c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4416c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4417c9005455SLois Curfman McInnes   during the section of code that is being timed.
4418c9005455SLois Curfman McInnes 
4419420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4420420bcc1bSBarry Smith 
44211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4422c9005455SLois Curfman McInnes @*/
4423d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4424d71ae5a4SJacob Faibussowitsch {
44253a40ed3dSBarry Smith   PetscFunctionBegin;
44260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44274f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44284f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44297a1ec6d4SBarry Smith   if (!a) {
443077e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44319566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4432071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4433308dcc3eSBarry Smith   }
4434c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4435758f92a0SBarry Smith   snes->conv_hist_its   = its;
4436115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4437a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4438758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4440758f92a0SBarry Smith }
4441758f92a0SBarry Smith 
4442d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4443c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4444c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
444599e0435eSBarry Smith 
4446d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4447d71ae5a4SJacob Faibussowitsch {
4448308dcc3eSBarry Smith   mxArray   *mat;
4449308dcc3eSBarry Smith   PetscInt   i;
4450308dcc3eSBarry Smith   PetscReal *ar;
4451308dcc3eSBarry Smith 
4452308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4453308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4454f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
445511cc89d2SBarry Smith   return mat;
4456308dcc3eSBarry Smith }
4457308dcc3eSBarry Smith #endif
4458308dcc3eSBarry Smith 
44590c4c9dddSBarry Smith /*@C
4460420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4461758f92a0SBarry Smith 
44623f9fe445SBarry Smith   Not Collective
4463758f92a0SBarry Smith 
4464758f92a0SBarry Smith   Input Parameter:
4465f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4466758f92a0SBarry Smith 
4467758f92a0SBarry Smith   Output Parameters:
4468f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4469758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4470758f92a0SBarry Smith          negative if not converged) for each solve.
447120f4b53cSBarry Smith - na  - size of `a` and `its`
4472758f92a0SBarry Smith 
4473dc4c0fb0SBarry Smith   Level: intermediate
4474dc4c0fb0SBarry Smith 
447520f4b53cSBarry Smith   Note:
447620f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
447720f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
447820f4b53cSBarry Smith   during the section of code that is being timed.
447920f4b53cSBarry Smith 
4480420bcc1bSBarry Smith   Fortran Note:
4481758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4482dc4c0fb0SBarry Smith .vb
4483dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4484dc4c0fb0SBarry Smith .ve
4485758f92a0SBarry Smith 
44861cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4487758f92a0SBarry Smith @*/
4488d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4489d71ae5a4SJacob Faibussowitsch {
4490758f92a0SBarry Smith   PetscFunctionBegin;
44910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4492758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4493758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4494115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
44953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4496c9005455SLois Curfman McInnes }
4497c9005455SLois Curfman McInnes 
4498ac226902SBarry Smith /*@C
449976b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4500eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
450153e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
450253e5d35bSStefano Zampini   evaluation.
450376b2cf59SMatthew Knepley 
4504c3339decSBarry Smith   Logically Collective
450576b2cf59SMatthew Knepley 
450676b2cf59SMatthew Knepley   Input Parameters:
4507a2b725a8SWilliam Gropp + snes - The nonlinear solver context
450853e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
450976b2cf59SMatthew Knepley 
4510fe97e370SBarry Smith   Level: advanced
4511fe97e370SBarry Smith 
4512420bcc1bSBarry Smith   Notes:
4513f6dfbefdSBarry 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
4514f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
451553e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
451653e5d35bSStefano Zampini   right before the direction step is computed.
451753e5d35bSStefano Zampini   Users are free to modify the current residual vector,
451853e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
451953e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
452053e5d35bSStefano Zampini   vectors.
452176b2cf59SMatthew Knepley 
4522aaa8cc7dSPierre 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.
45236b7fb656SBarry Smith 
4524e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
452553e5d35bSStefano Zampini          `SNESMonitorSet()`
452676b2cf59SMatthew Knepley @*/
452753e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4528d71ae5a4SJacob Faibussowitsch {
452976b2cf59SMatthew Knepley   PetscFunctionBegin;
45300700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4531e7788613SBarry Smith   snes->ops->update = func;
45323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
453376b2cf59SMatthew Knepley }
453476b2cf59SMatthew Knepley 
4535ffeef943SBarry Smith /*@
4536f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
45372a359c20SBarry Smith 
4538c3339decSBarry Smith   Collective
45392a359c20SBarry Smith 
4540e4094ef1SJacob Faibussowitsch   Input Parameters:
4541f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
45422a359c20SBarry Smith - viewer - the viewer to display the reason
45432a359c20SBarry Smith 
45442a359c20SBarry Smith   Options Database Keys:
4545ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4546ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4547eafd5ff0SAlex Lindsay 
4548420bcc1bSBarry Smith   Level: beginner
4549420bcc1bSBarry Smith 
4550f6dfbefdSBarry Smith   Note:
4551f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4552f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
45532a359c20SBarry Smith 
45541cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4555f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4556f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4557db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
45582a359c20SBarry Smith @*/
4559d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4560d71ae5a4SJacob Faibussowitsch {
456175cca76cSMatthew G. Knepley   PetscViewerFormat format;
45622a359c20SBarry Smith   PetscBool         isAscii;
45632a359c20SBarry Smith 
45642a359c20SBarry Smith   PetscFunctionBegin;
456519a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
45669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
45672a359c20SBarry Smith   if (isAscii) {
45689566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
456965bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
457075cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
457175cca76cSMatthew G. Knepley       DM       dm;
457275cca76cSMatthew G. Knepley       Vec      u;
457375cca76cSMatthew G. Knepley       PetscDS  prob;
457475cca76cSMatthew G. Knepley       PetscInt Nf, f;
457595cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
457695cbbfd3SMatthew G. Knepley       void    **exactCtx;
457775cca76cSMatthew G. Knepley       PetscReal error;
457875cca76cSMatthew G. Knepley 
45799566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
45809566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
45819566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
45829566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
45839566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
45849566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
45859566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
45869566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
45879566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
458863a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
458975cca76cSMatthew G. Knepley     }
4590eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
45912a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
459263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
45932a359c20SBarry Smith       } else {
459463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
45952a359c20SBarry Smith       }
4596eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
45972a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
459863a3b9bcSJacob 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));
45992a359c20SBarry Smith       } else {
460063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46012a359c20SBarry Smith       }
46022a359c20SBarry Smith     }
460365bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46042a359c20SBarry Smith   }
46053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46062a359c20SBarry Smith }
46072a359c20SBarry Smith 
4608c4421ceaSFande Kong /*@C
4609c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4610aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4611c4421ceaSFande Kong 
4612c3339decSBarry Smith   Logically Collective
4613c4421ceaSFande Kong 
4614c4421ceaSFande Kong   Input Parameters:
4615f6dfbefdSBarry Smith + snes              - the `SNES` context
4616420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4617420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4618*49abdd8aSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
4619420bcc1bSBarry Smith 
4620420bcc1bSBarry Smith   Calling sequence of `f`:
4621420bcc1bSBarry Smith + snes - the `SNES` context
4622*49abdd8aSBarry Smith - vctx - [optional] context for private data for the function
4623c4421ceaSFande Kong 
4624c4421ceaSFande Kong   Options Database Keys:
4625f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4626420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4627420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4628c4421ceaSFande Kong 
4629dc4c0fb0SBarry Smith   Level: intermediate
4630dc4c0fb0SBarry Smith 
4631f6dfbefdSBarry Smith   Note:
4632c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4633f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4634c4421ceaSFande Kong   order in which they were set.
4635c4421ceaSFande Kong 
4636*49abdd8aSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`,
4637*49abdd8aSBarry Smith           `PetscCtxDestroyFn`
4638c4421ceaSFande Kong @*/
4639*49abdd8aSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscCtxDestroyFn *reasonviewdestroy)
4640d71ae5a4SJacob Faibussowitsch {
4641c4421ceaSFande Kong   PetscInt  i;
4642c4421ceaSFande Kong   PetscBool identical;
4643c4421ceaSFande Kong 
4644c4421ceaSFande Kong   PetscFunctionBegin;
4645c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4646c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
46479566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
46483ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4649c4421ceaSFande Kong   }
46505f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4651c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4652c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4653c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
46543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4655c4421ceaSFande Kong }
4656c4421ceaSFande Kong 
465791f3e32bSBarry Smith /*@
4658420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4659c4421ceaSFande Kong   All the user-provided convergedReasonView routines will be involved as well, if they exist.
46602a359c20SBarry Smith 
4661c3339decSBarry Smith   Collective
46622a359c20SBarry Smith 
46632fe279fdSBarry Smith   Input Parameter:
4664f6dfbefdSBarry Smith . snes - the `SNES` object
46652a359c20SBarry Smith 
4666f6dfbefdSBarry Smith   Level: advanced
46672a359c20SBarry Smith 
46681cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4669f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
46702a359c20SBarry Smith @*/
4671d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4672d71ae5a4SJacob Faibussowitsch {
46732a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
46742a359c20SBarry Smith 
46752a359c20SBarry Smith   PetscFunctionBegin;
46763ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
46772a359c20SBarry Smith   incall = PETSC_TRUE;
4678c4421ceaSFande Kong 
4679c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
468036d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4681c4421ceaSFande Kong 
4682c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
468336d43d94SBarry Smith   if (snes->convergedreasonviewer) {
468436d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
468536d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
468636d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
46872a359c20SBarry Smith   }
46882a359c20SBarry Smith   incall = PETSC_FALSE;
46893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46902a359c20SBarry Smith }
46912a359c20SBarry Smith 
4692487a658cSBarry Smith /*@
4693f69a0ea3SMatthew Knepley   SNESSolve - Solves a nonlinear system F(x) = b.
46949b94acceSBarry Smith 
4695c3339decSBarry Smith   Collective
4696c7afd0dbSLois Curfman McInnes 
4697b2002411SLois Curfman McInnes   Input Parameters:
4698f6dfbefdSBarry Smith + snes - the `SNES` context
4699dc4c0fb0SBarry Smith . b    - the constant part of the equation F(x) = b, or `NULL` to use zero.
470085385478SLisandro Dalcin - x    - the solution vector.
47019b94acceSBarry Smith 
4702dc4c0fb0SBarry Smith   Level: beginner
4703dc4c0fb0SBarry Smith 
4704f6dfbefdSBarry Smith   Note:
4705420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4706420bcc1bSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
47078ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4708f6dfbefdSBarry Smith   this vector to zero by calling `VecSet()`.
47098ddd3da0SLois Curfman McInnes 
47101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4711db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4712420bcc1bSBarry Smith           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
47139b94acceSBarry Smith @*/
4714d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4715d71ae5a4SJacob Faibussowitsch {
4716ace3abfcSBarry Smith   PetscBool flg;
4717efd51863SBarry Smith   PetscInt  grid;
47180298fd71SBarry Smith   Vec       xcreated = NULL;
4719caa4e7f2SJed Brown   DM        dm;
4720052efed2SBarry Smith 
47213a40ed3dSBarry Smith   PetscFunctionBegin;
47220700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4723a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4724a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47250700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
472685385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
472785385478SLisandro Dalcin 
472834b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
472906fc46c8SMatthew G. Knepley   {
473006fc46c8SMatthew G. Knepley     PetscViewer       viewer;
473106fc46c8SMatthew G. Knepley     PetscViewerFormat format;
47327c88af5aSMatthew G. Knepley     PetscInt          num;
473306fc46c8SMatthew G. Knepley     PetscBool         flg;
473406fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
473506fc46c8SMatthew G. Knepley 
473606fc46c8SMatthew G. Knepley     if (!incall) {
473734b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4738648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
473906fc46c8SMatthew G. Knepley       if (flg) {
474006fc46c8SMatthew G. Knepley         PetscConvEst conv;
474146079b62SMatthew G. Knepley         DM           dm;
474246079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
474346079b62SMatthew G. Knepley         PetscInt     Nf;
474406fc46c8SMatthew G. Knepley 
474506fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
47469566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
47479566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
47489566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
47499566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
47509566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
47519566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
47529566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
47539566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
47549566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
47559566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
47569566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4757648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
47589566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
47599566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
476006fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
476106fc46c8SMatthew G. Knepley       }
476234b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4763b2588ea6SMatthew G. Knepley       num = 1;
47649566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
476534b4d3a8SMatthew G. Knepley       if (flg) {
476634b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
476734b4d3a8SMatthew G. Knepley 
476834b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
47699566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
47709566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
47719566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
47729566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
47739566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
47749566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
47759566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
477634b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
477734b4d3a8SMatthew G. Knepley       }
47787c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
47797c88af5aSMatthew G. Knepley       num = 0;
47809566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
47817c88af5aSMatthew G. Knepley       if (num) {
47827c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4783e03fd340SMatthew G. Knepley         const char *prefix;
47847c88af5aSMatthew G. Knepley 
47857c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
47869566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4787e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4788e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
47899566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
47909566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
47919566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
47929566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4793e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
47949566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
47959566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
47967c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
47977c88af5aSMatthew G. Knepley       }
479806fc46c8SMatthew G. Knepley     }
479906fc46c8SMatthew G. Knepley   }
4800ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4801caa4e7f2SJed Brown   if (!x) {
48029566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48039566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4804a69afd8bSBarry Smith     x = xcreated;
4805a69afd8bSBarry Smith   }
48069566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4807f05ece33SBarry Smith 
48089566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4809efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
481085385478SLisandro Dalcin     /* set solution vector */
48119566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48129566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
481385385478SLisandro Dalcin     snes->vec_sol = x;
48149566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4815caa4e7f2SJed Brown 
4816caa4e7f2SJed Brown     /* set affine vector if provided */
48179566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48189566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
481985385478SLisandro Dalcin     snes->vec_rhs = b;
482085385478SLisandro Dalcin 
48215f80ce2aSJacob 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");
48225f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4823dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4824aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48259566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48269566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48273f149594SLisandro Dalcin 
48287eee914bSBarry Smith     if (!grid) {
48299927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4830dd568438SSatish Balay     }
4831d25893d9SBarry Smith 
4832abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
483312b1dd1aSStefano Zampini     PetscCall(SNESResetCounters(snes));
48342d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
48359566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4836dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
48379566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
48382d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4839422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
48403f149594SLisandro Dalcin 
484137ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
484237ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
484337ec4e1aSPeter Brune 
4844648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
48459566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4846c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
48479566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
48485968eb51SBarry Smith 
48495f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
48509c8e83a9SBarry Smith     if (snes->reason < 0) break;
4851efd51863SBarry Smith     if (grid < snes->gridsequence) {
4852efd51863SBarry Smith       DM  fine;
4853efd51863SBarry Smith       Vec xnew;
4854efd51863SBarry Smith       Mat interp;
4855efd51863SBarry Smith 
48569566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
48575f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
48589566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
48599566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
48609566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
48619566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
48629566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4863efd51863SBarry Smith       x = xnew;
4864efd51863SBarry Smith 
48659566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
48669566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
48679566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
48689566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
48699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4870efd51863SBarry Smith     }
4871efd51863SBarry Smith   }
48729566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
48739566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
48749566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
48759566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
48763f7e2da0SPeter Brune 
48779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
48789566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
48793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48809b94acceSBarry Smith }
48819b94acceSBarry Smith 
48829b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
48839b94acceSBarry Smith 
4884cc4c1da9SBarry Smith /*@
48854b0e389bSBarry Smith   SNESSetType - Sets the method for the nonlinear solver.
48869b94acceSBarry Smith 
4887c3339decSBarry Smith   Collective
4888fee21e36SBarry Smith 
4889c7afd0dbSLois Curfman McInnes   Input Parameters:
4890f6dfbefdSBarry Smith + snes - the `SNES` context
4891454a90a3SBarry Smith - type - a known method
4892c7afd0dbSLois Curfman McInnes 
4893c7afd0dbSLois Curfman McInnes   Options Database Key:
4894454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
489504d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4896ae12b187SLois Curfman McInnes 
4897dc4c0fb0SBarry Smith   Level: intermediate
4898dc4c0fb0SBarry Smith 
48999b94acceSBarry Smith   Notes:
4900e090d566SSatish Balay   See "petsc/include/petscsnes.h" for available methods (for instance)
4901f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4902c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49034a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4904c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49059b94acceSBarry Smith 
4906f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4907f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4908ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4909ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4910f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4911ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4912ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4913ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4914ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4915b0a32e0cSBarry Smith   appropriate method.
491636851e7fSLois Curfman McInnes 
4917420bcc1bSBarry Smith   Developer Note:
4918f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4919f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
49208f6c3df8SBarry Smith 
49211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49229b94acceSBarry Smith @*/
4923d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4924d71ae5a4SJacob Faibussowitsch {
4925ace3abfcSBarry Smith   PetscBool match;
49265f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
49273a40ed3dSBarry Smith 
49283a40ed3dSBarry Smith   PetscFunctionBegin;
49290700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49304f572ea9SToby Isaac   PetscAssertPointer(type, 2);
493182bf6240SBarry Smith 
49329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
49333ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
493492ff6ae8SBarry Smith 
49359566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
49366adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
493775396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4938dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
493975396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
49409e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
49419e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
49429e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
49439e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
49449e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
49457fe760d5SStefano Zampini 
49467fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
49479566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
49487fe760d5SStefano Zampini 
494975396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
495075396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4951f5af7f23SKarl Rupp 
49529566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
49539566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
49543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49559b94acceSBarry Smith }
49569b94acceSBarry Smith 
4957cc4c1da9SBarry Smith /*@
4958f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
49599b94acceSBarry Smith 
4960c7afd0dbSLois Curfman McInnes   Not Collective
4961c7afd0dbSLois Curfman McInnes 
49629b94acceSBarry Smith   Input Parameter:
49634b0e389bSBarry Smith . snes - nonlinear solver context
49649b94acceSBarry Smith 
49659b94acceSBarry Smith   Output Parameter:
4966f6dfbefdSBarry Smith . type - `SNES` method (a character string)
49679b94acceSBarry Smith 
496836851e7fSLois Curfman McInnes   Level: intermediate
496936851e7fSLois Curfman McInnes 
49701cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
49719b94acceSBarry Smith @*/
4972d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4973d71ae5a4SJacob Faibussowitsch {
49743a40ed3dSBarry Smith   PetscFunctionBegin;
49750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49764f572ea9SToby Isaac   PetscAssertPointer(type, 2);
49777adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
49783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49799b94acceSBarry Smith }
49809b94acceSBarry Smith 
49813cd8a7caSMatthew G. Knepley /*@
4982f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
49833cd8a7caSMatthew G. Knepley 
4984c3339decSBarry Smith   Logically Collective
49853cd8a7caSMatthew G. Knepley 
49863cd8a7caSMatthew G. Knepley   Input Parameters:
4987f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
49883cd8a7caSMatthew G. Knepley - u    - the solution vector
49893cd8a7caSMatthew G. Knepley 
49903cd8a7caSMatthew G. Knepley   Level: beginner
49913cd8a7caSMatthew G. Knepley 
49921cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
49933cd8a7caSMatthew G. Knepley @*/
4994d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
4995d71ae5a4SJacob Faibussowitsch {
49963cd8a7caSMatthew G. Knepley   DM dm;
49973cd8a7caSMatthew G. Knepley 
49983cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
49993cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50003cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50019566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
50029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
50033cd8a7caSMatthew G. Knepley 
50043cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
50053cd8a7caSMatthew G. Knepley 
50069566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50079566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
50083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50093cd8a7caSMatthew G. Knepley }
50103cd8a7caSMatthew G. Knepley 
501152baeb72SSatish Balay /*@
50129b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
5013f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50149b94acceSBarry Smith 
5015420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5016c7afd0dbSLois Curfman McInnes 
50179b94acceSBarry Smith   Input Parameter:
5018f6dfbefdSBarry Smith . snes - the `SNES` context
50199b94acceSBarry Smith 
50209b94acceSBarry Smith   Output Parameter:
50219b94acceSBarry Smith . x - the solution
50229b94acceSBarry Smith 
502370e92668SMatthew Knepley   Level: intermediate
502436851e7fSLois Curfman McInnes 
50251cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
50269b94acceSBarry Smith @*/
5027d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5028d71ae5a4SJacob Faibussowitsch {
50293a40ed3dSBarry Smith   PetscFunctionBegin;
50300700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50314f572ea9SToby Isaac   PetscAssertPointer(x, 2);
503285385478SLisandro Dalcin   *x = snes->vec_sol;
50333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
503470e92668SMatthew Knepley }
503570e92668SMatthew Knepley 
503652baeb72SSatish Balay /*@
50379b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
50389b94acceSBarry Smith   stored.
50399b94acceSBarry Smith 
5040420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5041c7afd0dbSLois Curfman McInnes 
50429b94acceSBarry Smith   Input Parameter:
5043f6dfbefdSBarry Smith . snes - the `SNES` context
50449b94acceSBarry Smith 
50459b94acceSBarry Smith   Output Parameter:
50469b94acceSBarry Smith . x - the solution update
50479b94acceSBarry Smith 
504836851e7fSLois Curfman McInnes   Level: advanced
504936851e7fSLois Curfman McInnes 
50501cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
50519b94acceSBarry Smith @*/
5052d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5053d71ae5a4SJacob Faibussowitsch {
50543a40ed3dSBarry Smith   PetscFunctionBegin;
50550700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50564f572ea9SToby Isaac   PetscAssertPointer(x, 2);
505785385478SLisandro Dalcin   *x = snes->vec_sol_update;
50583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50599b94acceSBarry Smith }
50609b94acceSBarry Smith 
50619b94acceSBarry Smith /*@C
5062f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
50639b94acceSBarry Smith 
5064420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5065c7afd0dbSLois Curfman McInnes 
50669b94acceSBarry Smith   Input Parameter:
5067f6dfbefdSBarry Smith . snes - the `SNES` context
50689b94acceSBarry Smith 
5069d8d19677SJose E. Roman   Output Parameters:
5070dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
50718434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5072dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
50739b94acceSBarry Smith 
507436851e7fSLois Curfman McInnes   Level: advanced
507536851e7fSLois Curfman McInnes 
5076f6dfbefdSBarry Smith   Note:
5077dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
507804edfde5SBarry Smith 
50798434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
50809b94acceSBarry Smith @*/
50818434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5082d71ae5a4SJacob Faibussowitsch {
50836cab3a1bSJed Brown   DM dm;
5084a63bb30eSJed Brown 
50853a40ed3dSBarry Smith   PetscFunctionBegin;
50860700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5087a63bb30eSJed Brown   if (r) {
5088a63bb30eSJed Brown     if (!snes->vec_func) {
5089a63bb30eSJed Brown       if (snes->vec_rhs) {
50909566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5091a63bb30eSJed Brown       } else if (snes->vec_sol) {
50929566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5093a63bb30eSJed Brown       } else if (snes->dm) {
50949566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5095a63bb30eSJed Brown       }
5096a63bb30eSJed Brown     }
5097a63bb30eSJed Brown     *r = snes->vec_func;
5098a63bb30eSJed Brown   }
50999566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51009566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
51013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51029b94acceSBarry Smith }
51039b94acceSBarry Smith 
5104c79ef259SPeter Brune /*@C
510537fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5106c79ef259SPeter Brune 
5107c79ef259SPeter Brune   Input Parameter:
5108f6dfbefdSBarry Smith . snes - the `SNES` context
5109c79ef259SPeter Brune 
5110d8d19677SJose E. Roman   Output Parameters:
51118434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5112dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5113c79ef259SPeter Brune 
5114c79ef259SPeter Brune   Level: advanced
5115c79ef259SPeter Brune 
51168434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5117c79ef259SPeter Brune @*/
51188434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5119d71ae5a4SJacob Faibussowitsch {
51206cab3a1bSJed Brown   DM dm;
51216cab3a1bSJed Brown 
5122646217ecSPeter Brune   PetscFunctionBegin;
5123646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51249566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51259566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
51263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5127646217ecSPeter Brune }
5128646217ecSPeter Brune 
5129cc4c1da9SBarry Smith /*@
51303c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5131f6dfbefdSBarry Smith   `SNES` options in the database.
51323c7409f5SSatish Balay 
5133c3339decSBarry Smith   Logically Collective
5134fee21e36SBarry Smith 
5135d8d19677SJose E. Roman   Input Parameters:
5136f6dfbefdSBarry Smith + snes   - the `SNES` context
5137c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5138c7afd0dbSLois Curfman McInnes 
5139dc4c0fb0SBarry Smith   Level: advanced
5140dc4c0fb0SBarry Smith 
5141f6dfbefdSBarry Smith   Note:
5142a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5143c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5144d850072dSLois Curfman McInnes 
51451cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
51463c7409f5SSatish Balay @*/
5147d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5148d71ae5a4SJacob Faibussowitsch {
51493a40ed3dSBarry Smith   PetscFunctionBegin;
51500700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51519566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
51529566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
515335f5d045SPeter Brune   if (snes->linesearch) {
51549566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51559566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
515635f5d045SPeter Brune   }
51579566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
51583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51593c7409f5SSatish Balay }
51603c7409f5SSatish Balay 
5161cc4c1da9SBarry Smith /*@
5162f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5163f6dfbefdSBarry Smith   `SNES` options in the database.
51643c7409f5SSatish Balay 
5165c3339decSBarry Smith   Logically Collective
5166fee21e36SBarry Smith 
5167c7afd0dbSLois Curfman McInnes   Input Parameters:
5168f6dfbefdSBarry Smith + snes   - the `SNES` context
5169c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5170c7afd0dbSLois Curfman McInnes 
5171dc4c0fb0SBarry Smith   Level: advanced
5172dc4c0fb0SBarry Smith 
5173f6dfbefdSBarry Smith   Note:
5174a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5175c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5176d850072dSLois Curfman McInnes 
51771cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
51783c7409f5SSatish Balay @*/
5179d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5180d71ae5a4SJacob Faibussowitsch {
51813a40ed3dSBarry Smith   PetscFunctionBegin;
51820700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51839566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
51849566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
518535f5d045SPeter Brune   if (snes->linesearch) {
51869566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51879566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
518835f5d045SPeter Brune   }
51899566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
51903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51913c7409f5SSatish Balay }
51923c7409f5SSatish Balay 
5193cc4c1da9SBarry Smith /*@
5194f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5195f6dfbefdSBarry Smith   `SNES` options in the database.
51963c7409f5SSatish Balay 
5197c7afd0dbSLois Curfman McInnes   Not Collective
5198c7afd0dbSLois Curfman McInnes 
51993c7409f5SSatish Balay   Input Parameter:
5200f6dfbefdSBarry Smith . snes - the `SNES` context
52013c7409f5SSatish Balay 
52023c7409f5SSatish Balay   Output Parameter:
52033c7409f5SSatish Balay . prefix - pointer to the prefix string used
52043c7409f5SSatish Balay 
520536851e7fSLois Curfman McInnes   Level: advanced
520636851e7fSLois Curfman McInnes 
5207420bcc1bSBarry Smith   Fortran Note:
5208dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5209dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5210dc4c0fb0SBarry Smith 
52111cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52123c7409f5SSatish Balay @*/
5213d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5214d71ae5a4SJacob Faibussowitsch {
52153a40ed3dSBarry Smith   PetscFunctionBegin;
52160700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52179566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52193c7409f5SSatish Balay }
52203c7409f5SSatish Balay 
52213cea93caSBarry Smith /*@C
52221c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
52231c84c290SBarry Smith 
522420f4b53cSBarry Smith   Not Collective
52251c84c290SBarry Smith 
52261c84c290SBarry Smith   Input Parameters:
522720f4b53cSBarry Smith + sname    - name of a new user-defined solver
522820f4b53cSBarry Smith - function - routine to create method context
52291c84c290SBarry Smith 
5230dc4c0fb0SBarry Smith   Level: advanced
5231dc4c0fb0SBarry Smith 
5232f6dfbefdSBarry Smith   Note:
5233f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
52341c84c290SBarry Smith 
5235e4094ef1SJacob Faibussowitsch   Example Usage:
52361c84c290SBarry Smith .vb
5237bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
52381c84c290SBarry Smith .ve
52391c84c290SBarry Smith 
52401c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
52411c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
52421c84c290SBarry Smith   or at runtime via the option
52431c84c290SBarry Smith $     -snes_type my_solver
52441c84c290SBarry Smith 
52451cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
52463cea93caSBarry Smith @*/
5247d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5248d71ae5a4SJacob Faibussowitsch {
5249b2002411SLois Curfman McInnes   PetscFunctionBegin;
52509566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
52519566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
52523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5253b2002411SLois Curfman McInnes }
5254da9b6338SBarry Smith 
5255d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5256d71ae5a4SJacob Faibussowitsch {
525777431f27SBarry Smith   PetscInt    N, i, j;
5258da9b6338SBarry Smith   Vec         u, uh, fh;
5259da9b6338SBarry Smith   PetscScalar value;
5260da9b6338SBarry Smith   PetscReal   norm;
5261da9b6338SBarry Smith 
5262da9b6338SBarry Smith   PetscFunctionBegin;
52639566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
52649566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
52659566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5266da9b6338SBarry Smith 
5267da9b6338SBarry Smith   /* currently only works for sequential */
52689566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
52699566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5270da9b6338SBarry Smith   for (i = 0; i < N; i++) {
52719566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
527263a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5273da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
52748b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
52759566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
52769566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
52779566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
527863a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5279da9b6338SBarry Smith       value = -value;
52809566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5281da9b6338SBarry Smith     }
5282da9b6338SBarry Smith   }
52839566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
52849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
52853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5286da9b6338SBarry Smith }
528771f87433Sdalcinl 
528871f87433Sdalcinl /*@
5289f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
529071f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
529171f87433Sdalcinl   Newton method.
529271f87433Sdalcinl 
5293c3339decSBarry Smith   Logically Collective
529471f87433Sdalcinl 
529571f87433Sdalcinl   Input Parameters:
5296f6dfbefdSBarry Smith + snes - `SNES` context
5297f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
529871f87433Sdalcinl 
5299f6dfbefdSBarry Smith   Options Database Keys:
530064ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
530164ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
530264ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
530364ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
530464ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
530564ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
530664ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
530764ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
530864ba62caSBarry Smith 
5309dc4c0fb0SBarry Smith   Level: advanced
5310dc4c0fb0SBarry Smith 
5311f6dfbefdSBarry Smith   Note:
5312f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
531371f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
53141d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
531571f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
531671f87433Sdalcinl   solver.
531771f87433Sdalcinl 
53181cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
531971f87433Sdalcinl @*/
5320d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5321d71ae5a4SJacob Faibussowitsch {
532271f87433Sdalcinl   PetscFunctionBegin;
53230700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5324acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
532571f87433Sdalcinl   snes->ksp_ewconv = flag;
53263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
532771f87433Sdalcinl }
532871f87433Sdalcinl 
532971f87433Sdalcinl /*@
5330f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
533171f87433Sdalcinl   for computing relative tolerance for linear solvers within an
533271f87433Sdalcinl   inexact Newton method.
533371f87433Sdalcinl 
533471f87433Sdalcinl   Not Collective
533571f87433Sdalcinl 
533671f87433Sdalcinl   Input Parameter:
5337f6dfbefdSBarry Smith . snes - `SNES` context
533871f87433Sdalcinl 
533971f87433Sdalcinl   Output Parameter:
5340f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
534171f87433Sdalcinl 
534271f87433Sdalcinl   Level: advanced
534371f87433Sdalcinl 
53441cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
534571f87433Sdalcinl @*/
5346d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5347d71ae5a4SJacob Faibussowitsch {
534871f87433Sdalcinl   PetscFunctionBegin;
53490700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
53504f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
535171f87433Sdalcinl   *flag = snes->ksp_ewconv;
53523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
535371f87433Sdalcinl }
535471f87433Sdalcinl 
535571f87433Sdalcinl /*@
5356fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
535771f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
535871f87433Sdalcinl   Newton method.
535971f87433Sdalcinl 
5360c3339decSBarry Smith   Logically Collective
536171f87433Sdalcinl 
536271f87433Sdalcinl   Input Parameters:
5363f6dfbefdSBarry Smith + snes      - `SNES` context
53640f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
536571f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
536671f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
536771f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
536871f87433Sdalcinl              (0 <= gamma2 <= 1)
536971f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
537071f87433Sdalcinl . alpha2    - power for safeguard
537171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
537271f87433Sdalcinl 
5373dc4c0fb0SBarry Smith   Level: advanced
5374dc4c0fb0SBarry Smith 
5375f6dfbefdSBarry Smith   Notes:
537671f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
537771f87433Sdalcinl 
537877e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
537971f87433Sdalcinl 
53801cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
538171f87433Sdalcinl @*/
5382d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5383d71ae5a4SJacob Faibussowitsch {
5384fa9f3622SBarry Smith   SNESKSPEW *kctx;
53855fd66863SKarl Rupp 
538671f87433Sdalcinl   PetscFunctionBegin;
53870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5388fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53895f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5390c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5391c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5392c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5393c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5394c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5395c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5396c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
539771f87433Sdalcinl 
539877e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
539977e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
540077e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
540177e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
540277e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
540377e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
540477e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
540571f87433Sdalcinl 
54060f0abf79SStefano 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);
54070b121fc5SBarry 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);
54080b121fc5SBarry 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);
54090b121fc5SBarry 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);
54100b121fc5SBarry 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);
54110b121fc5SBarry 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);
54123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
541371f87433Sdalcinl }
541471f87433Sdalcinl 
541571f87433Sdalcinl /*@
5416fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
541771f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
541871f87433Sdalcinl   Newton method.
541971f87433Sdalcinl 
542071f87433Sdalcinl   Not Collective
542171f87433Sdalcinl 
542297bb3fdcSJose E. Roman   Input Parameter:
5423f6dfbefdSBarry Smith . snes - `SNES` context
542471f87433Sdalcinl 
542571f87433Sdalcinl   Output Parameters:
54260f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
542771f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
542871f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5429bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
543071f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
543171f87433Sdalcinl . alpha2    - power for safeguard
543271f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
543371f87433Sdalcinl 
543471f87433Sdalcinl   Level: advanced
543571f87433Sdalcinl 
54361cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
543771f87433Sdalcinl @*/
5438d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5439d71ae5a4SJacob Faibussowitsch {
5440fa9f3622SBarry Smith   SNESKSPEW *kctx;
54415fd66863SKarl Rupp 
544271f87433Sdalcinl   PetscFunctionBegin;
54430700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5444fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54455f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
544671f87433Sdalcinl   if (version) *version = kctx->version;
544771f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
544871f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
544971f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
545071f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
545171f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
545271f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
54533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545471f87433Sdalcinl }
545571f87433Sdalcinl 
54565c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5457d71ae5a4SJacob Faibussowitsch {
54585c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5459fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
546077e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
546171f87433Sdalcinl 
546271f87433Sdalcinl   PetscFunctionBegin;
54633ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
546430058271SDmitry Karpeev   if (!snes->iter) {
546530058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
54669566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
54670f0abf79SStefano Zampini   } else {
54680fdf79fbSJacob 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);
546971f87433Sdalcinl     if (kctx->version == 1) {
54700f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
547185ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
547271f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
547371f87433Sdalcinl     } else if (kctx->version == 2) {
547485ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
547585ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
547671f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
547771f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
547885ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
547971f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
548085ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
548171f87433Sdalcinl       stol = PetscMax(rtol, stol);
548271f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
548371f87433Sdalcinl       /* safeguard: avoid oversolving */
548430058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
548571f87433Sdalcinl       stol = PetscMax(rtol, stol);
548671f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
54870fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
54880fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
54890f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
54900f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
54910f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
54920f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
54930f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
54940f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
54950f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
54960f0abf79SStefano Zampini 
5497a4598233SStefano 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;
54980f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
54990f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
55000f0abf79SStefano Zampini       kctx->rk_last     = rk;
55010fdf79fbSJacob Faibussowitsch     }
55020f0abf79SStefano Zampini   }
55030f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
550471f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
550577e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
550663a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
55073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
550871f87433Sdalcinl }
550971f87433Sdalcinl 
55105c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5511d71ae5a4SJacob Faibussowitsch {
55125c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5513fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
551471f87433Sdalcinl   PCSide     pcside;
551571f87433Sdalcinl   Vec        lres;
551671f87433Sdalcinl 
551771f87433Sdalcinl   PetscFunctionBegin;
55183ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
55199566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
552071dbe336SPeter Brune   kctx->norm_last = snes->norm;
55210f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
55224f00ce20SMatthew G. Knepley     PC        pc;
55230f0abf79SStefano Zampini     PetscBool getRes;
55244f00ce20SMatthew G. Knepley 
55259566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
55260f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
55270f0abf79SStefano Zampini     if (!getRes) {
55280f0abf79SStefano Zampini       KSPNormType normtype;
55290f0abf79SStefano Zampini 
55300f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
55310f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
55320f0abf79SStefano Zampini     }
55339566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
55340f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
55359566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
553671f87433Sdalcinl     } else {
553771f87433Sdalcinl       /* KSP residual is preconditioned residual */
553871f87433Sdalcinl       /* compute true linear residual norm */
55390f0abf79SStefano Zampini       Mat J;
55400f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
55419566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
55420f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
55439566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
55449566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
55459566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
554671f87433Sdalcinl     }
554771f87433Sdalcinl   }
55483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
554971f87433Sdalcinl }
555071f87433Sdalcinl 
5551d4211eb9SBarry Smith /*@
5552f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5553d4211eb9SBarry Smith 
5554420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5555d4211eb9SBarry Smith 
5556d4211eb9SBarry Smith   Input Parameter:
5557f6dfbefdSBarry Smith . snes - the `SNES` context
5558d4211eb9SBarry Smith 
5559d4211eb9SBarry Smith   Output Parameter:
5560f6dfbefdSBarry Smith . ksp - the `KSP` context
5561d4211eb9SBarry Smith 
5562dc4c0fb0SBarry Smith   Level: beginner
5563dc4c0fb0SBarry Smith 
5564d4211eb9SBarry Smith   Notes:
5565f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5566d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5567f6dfbefdSBarry Smith   `PC` contexts as well.
5568f6dfbefdSBarry Smith 
5569f6dfbefdSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function
5570d4211eb9SBarry Smith 
55711cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5572d4211eb9SBarry Smith @*/
5573d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5574d71ae5a4SJacob Faibussowitsch {
557571f87433Sdalcinl   PetscFunctionBegin;
5576d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55774f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5578d4211eb9SBarry Smith 
5579d4211eb9SBarry Smith   if (!snes->ksp) {
55809566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
55819566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5582d4211eb9SBarry Smith 
55835c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
55845c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5585a5c2985bSBarry Smith 
55869566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
55879566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5588d4211eb9SBarry Smith   }
5589d4211eb9SBarry Smith   *ksp = snes->ksp;
55903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
559171f87433Sdalcinl }
55926c699258SBarry Smith 
5593af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
55946c699258SBarry Smith /*@
5595f6dfbefdSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some nonlinear solvers or their underlying preconditioners
55966c699258SBarry Smith 
5597c3339decSBarry Smith   Logically Collective
55986c699258SBarry Smith 
55996c699258SBarry Smith   Input Parameters:
56002a808120SBarry Smith + snes - the nonlinear solver context
5601420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5602dc4c0fb0SBarry Smith 
5603dc4c0fb0SBarry Smith   Level: intermediate
56046c699258SBarry Smith 
5605f6dfbefdSBarry Smith   Note:
5606f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5607f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5608e03a659cSJed Brown   problems using the same function space.
5609e03a659cSJed Brown 
5610420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
56116c699258SBarry Smith @*/
5612d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5613d71ae5a4SJacob Faibussowitsch {
5614345fed2cSBarry Smith   KSP    ksp;
5615942e3340SBarry Smith   DMSNES sdm;
56166c699258SBarry Smith 
56176c699258SBarry Smith   PetscFunctionBegin;
56180700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56192a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
56209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5621942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
562251f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
56239566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
56249566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5625f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
56266cab3a1bSJed Brown     }
56279566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
56289566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
56296cab3a1bSJed Brown   }
56306c699258SBarry Smith   snes->dm     = dm;
5631116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5632f5af7f23SKarl Rupp 
56339566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
56349566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
56359566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5636efd4aadfSBarry Smith   if (snes->npc) {
56379566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
56389566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
56392c155ee1SBarry Smith   }
56403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56416c699258SBarry Smith }
56426c699258SBarry Smith 
56436c699258SBarry Smith /*@
5644420bcc1bSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some solvers/preconditioners
56456c699258SBarry Smith 
5646f6dfbefdSBarry Smith   Not Collective but dm obtained is parallel on snes
56476c699258SBarry Smith 
56486c699258SBarry Smith   Input Parameter:
5649420bcc1bSBarry Smith . snes - the `SNES` context
56506c699258SBarry Smith 
56516c699258SBarry Smith   Output Parameter:
5652420bcc1bSBarry Smith . dm - the `DM`
56536c699258SBarry Smith 
56546c699258SBarry Smith   Level: intermediate
56556c699258SBarry Smith 
5656420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
56576c699258SBarry Smith @*/
5658d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5659d71ae5a4SJacob Faibussowitsch {
56606c699258SBarry Smith   PetscFunctionBegin;
56610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56626cab3a1bSJed Brown   if (!snes->dm) {
56639566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5664116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
56656cab3a1bSJed Brown   }
56666c699258SBarry Smith   *dm = snes->dm;
56673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56686c699258SBarry Smith }
56690807856dSBarry Smith 
567031823bd8SMatthew G Knepley /*@
5671be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
567231823bd8SMatthew G Knepley 
5673c3339decSBarry Smith   Collective
567431823bd8SMatthew G Knepley 
567531823bd8SMatthew G Knepley   Input Parameters:
5676f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5677420bcc1bSBarry Smith - npc  - the nonlinear preconditioner object
567831823bd8SMatthew G Knepley 
5679dc4c0fb0SBarry Smith   Level: developer
5680dc4c0fb0SBarry Smith 
568131823bd8SMatthew G Knepley   Notes:
5682f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
568331823bd8SMatthew G Knepley   to configure it using the API).
568431823bd8SMatthew G Knepley 
5685f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5686f6dfbefdSBarry Smith 
5687420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
568831823bd8SMatthew G Knepley @*/
5689d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5690d71ae5a4SJacob Faibussowitsch {
569131823bd8SMatthew G Knepley   PetscFunctionBegin;
569231823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5693f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5694f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5695f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
56969566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5697f6dfbefdSBarry Smith   snes->npc = npc;
56983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
569931823bd8SMatthew G Knepley }
570031823bd8SMatthew G Knepley 
570131823bd8SMatthew G Knepley /*@
5702f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
570331823bd8SMatthew G Knepley 
5704f6dfbefdSBarry Smith   Not Collective; but any changes to the obtained the npc object must be applied collectively
570531823bd8SMatthew G Knepley 
570631823bd8SMatthew G Knepley   Input Parameter:
5707f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
570831823bd8SMatthew G Knepley 
570931823bd8SMatthew G Knepley   Output Parameter:
5710e4094ef1SJacob Faibussowitsch . pc - preconditioner context
571131823bd8SMatthew G Knepley 
5712f6dfbefdSBarry Smith   Options Database Key:
5713f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5714b5badacbSBarry Smith 
5715dc4c0fb0SBarry Smith   Level: developer
5716dc4c0fb0SBarry Smith 
571795452b02SPatrick Sanan   Notes:
5718f6dfbefdSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created.
5719be95d8f1SBarry Smith 
5720f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5721f6dfbefdSBarry Smith   `SNES`
5722951fe5abSBarry Smith 
57231cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
572431823bd8SMatthew G Knepley @*/
5725d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5726d71ae5a4SJacob Faibussowitsch {
5727a64e098fSPeter Brune   const char *optionsprefix;
572831823bd8SMatthew G Knepley 
572931823bd8SMatthew G Knepley   PetscFunctionBegin;
573031823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57314f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5732efd4aadfSBarry Smith   if (!snes->npc) {
5733ec785e5bSStefano Zampini     void *ctx;
5734ec785e5bSStefano Zampini 
57359566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
57369566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
57379566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57389566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
57399566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5740fb87a551SStefano Zampini     if (snes->ops->usercompute) {
5741*49abdd8aSBarry Smith       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->ctxdestroy));
5742fb87a551SStefano Zampini     } else {
5743ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5744ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5745fb87a551SStefano Zampini     }
57469566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
574731823bd8SMatthew G Knepley   }
5748efd4aadfSBarry Smith   *pc = snes->npc;
57493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
575031823bd8SMatthew G Knepley }
575131823bd8SMatthew G Knepley 
57523ad1a0b9SPatrick Farrell /*@
57533ad1a0b9SPatrick Farrell   SNESHasNPC - Returns whether a nonlinear preconditioner exists
57543ad1a0b9SPatrick Farrell 
57553ad1a0b9SPatrick Farrell   Not Collective
57563ad1a0b9SPatrick Farrell 
57573ad1a0b9SPatrick Farrell   Input Parameter:
5758f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57593ad1a0b9SPatrick Farrell 
57603ad1a0b9SPatrick Farrell   Output Parameter:
5761420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
57623ad1a0b9SPatrick Farrell 
57633ad1a0b9SPatrick Farrell   Level: developer
57643ad1a0b9SPatrick Farrell 
57651cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
57663ad1a0b9SPatrick Farrell @*/
5767d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5768d71ae5a4SJacob Faibussowitsch {
57693ad1a0b9SPatrick Farrell   PetscFunctionBegin;
57703ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5771efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
57723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57733ad1a0b9SPatrick Farrell }
57743ad1a0b9SPatrick Farrell 
5775c40d0f55SPeter Brune /*@
5776420bcc1bSBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side.
5777c40d0f55SPeter Brune 
5778c3339decSBarry Smith   Logically Collective
5779c40d0f55SPeter Brune 
5780c40d0f55SPeter Brune   Input Parameter:
5781f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5782c40d0f55SPeter Brune 
5783c40d0f55SPeter Brune   Output Parameter:
5784c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5785c40d0f55SPeter Brune .vb
57862d547940SBarry Smith       PC_LEFT - left preconditioning
57872d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5788c40d0f55SPeter Brune .ve
5789c40d0f55SPeter Brune 
5790f6dfbefdSBarry Smith   Options Database Key:
579167b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5792c40d0f55SPeter Brune 
5793dc4c0fb0SBarry Smith   Level: intermediate
5794dc4c0fb0SBarry Smith 
5795f6dfbefdSBarry Smith   Note:
5796f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
57972d547940SBarry Smith 
5798420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5799c40d0f55SPeter Brune @*/
5800d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5801d71ae5a4SJacob Faibussowitsch {
5802c40d0f55SPeter Brune   PetscFunctionBegin;
5803c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5804c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5805b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
580654c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5807efd4aadfSBarry Smith   snes->npcside = side;
58083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5809c40d0f55SPeter Brune }
5810c40d0f55SPeter Brune 
5811c40d0f55SPeter Brune /*@
5812be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5813c40d0f55SPeter Brune 
5814c40d0f55SPeter Brune   Not Collective
5815c40d0f55SPeter Brune 
5816c40d0f55SPeter Brune   Input Parameter:
5817f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5818c40d0f55SPeter Brune 
5819c40d0f55SPeter Brune   Output Parameter:
5820c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5821c40d0f55SPeter Brune .vb
5822f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5823f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5824c40d0f55SPeter Brune .ve
5825c40d0f55SPeter Brune 
5826c40d0f55SPeter Brune   Level: intermediate
5827c40d0f55SPeter Brune 
5828420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5829c40d0f55SPeter Brune @*/
5830d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5831d71ae5a4SJacob Faibussowitsch {
5832c40d0f55SPeter Brune   PetscFunctionBegin;
5833c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58344f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5835efd4aadfSBarry Smith   *side = snes->npcside;
58363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5837c40d0f55SPeter Brune }
5838c40d0f55SPeter Brune 
58399e764e56SPeter Brune /*@
5840420bcc1bSBarry Smith   SNESSetLineSearch - Sets the linesearch to be used for `SNES`
58419e764e56SPeter Brune 
5842c3339decSBarry Smith   Collective
58439e764e56SPeter Brune 
58449e764e56SPeter Brune   Input Parameters:
5845f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
58469e764e56SPeter Brune - linesearch - the linesearch object
58479e764e56SPeter Brune 
5848dc4c0fb0SBarry Smith   Level: developer
5849dc4c0fb0SBarry Smith 
5850f6dfbefdSBarry Smith   Note:
5851420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
58529e764e56SPeter Brune   to configure it using the API).
58539e764e56SPeter Brune 
5854420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
58559e764e56SPeter Brune @*/
5856d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5857d71ae5a4SJacob Faibussowitsch {
58589e764e56SPeter Brune   PetscFunctionBegin;
58599e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5860f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
58619e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
58629566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
58639566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5864f5af7f23SKarl Rupp 
58659e764e56SPeter Brune   snes->linesearch = linesearch;
58663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58679e764e56SPeter Brune }
58689e764e56SPeter Brune 
5869a34ceb2aSJed Brown /*@
5870420bcc1bSBarry Smith   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5871f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
58729e764e56SPeter Brune 
58739e764e56SPeter Brune   Not Collective
58749e764e56SPeter Brune 
58759e764e56SPeter Brune   Input Parameter:
5876f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58779e764e56SPeter Brune 
58789e764e56SPeter Brune   Output Parameter:
58799e764e56SPeter Brune . linesearch - linesearch context
58809e764e56SPeter Brune 
5881162e0bf5SPeter Brune   Level: beginner
58829e764e56SPeter Brune 
58831cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
58849e764e56SPeter Brune @*/
5885d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5886d71ae5a4SJacob Faibussowitsch {
58879e764e56SPeter Brune   const char *optionsprefix;
58889e764e56SPeter Brune 
58899e764e56SPeter Brune   PetscFunctionBegin;
58909e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58914f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
58929e764e56SPeter Brune   if (!snes->linesearch) {
58939566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
58949566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
58959566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
58969566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
58979566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
58989e764e56SPeter Brune   }
58999e764e56SPeter Brune   *linesearch = snes->linesearch;
59003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59019e764e56SPeter Brune }
5902