xref: /petsc/src/snes/interface/snes.c (revision 0b4b7b1c20c2ed4ade67e3d50a7710fe0ffbfca5)
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
855fde5950dSBarry Smith . monitor      - the monitor function
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));
8949566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, (PetscErrorCode (*)(SNES, PetscInt, PetscReal, void *))monitor, vf, (PetscErrorCode (*)(void **))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));
11069566063dSJacob Faibussowitsch     PetscCall(SNESMonitorSet(snes, SNESMonitorLGRange, ctx, (PetscErrorCode (*)(void **))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
1234d25893d9SBarry Smith - destroy - function to destroy the context
1235d25893d9SBarry Smith 
1236420bcc1bSBarry Smith   Calling sequence of `compute`:
1237420bcc1bSBarry Smith + snes - the `SNES` context
1238420bcc1bSBarry Smith - ctx  - context to be computed
1239420bcc1bSBarry Smith 
1240420bcc1bSBarry Smith   Calling sequence of `destroy`:
1241420bcc1bSBarry Smith . ctx - context to be computed by `compute()`
1242420bcc1bSBarry Smith 
1243d25893d9SBarry Smith   Level: intermediate
1244d25893d9SBarry Smith 
1245f6dfbefdSBarry Smith   Note:
1246f6dfbefdSBarry Smith   This routine is useful if you are performing grid sequencing or using `SNESFAS` and need the appropriate context generated for each level.
1247f6dfbefdSBarry Smith 
1248f6dfbefdSBarry Smith   Use `SNESSetApplicationContext()` to see the context immediately
1249f6dfbefdSBarry Smith 
125042747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESGetApplicationContext()`, `SNESSetApplicationContext()`
1251d25893d9SBarry Smith @*/
1252420bcc1bSBarry Smith PetscErrorCode SNESSetComputeApplicationContext(SNES snes, PetscErrorCode (*compute)(SNES snes, void **ctx), PetscErrorCode (*destroy)(void **ctx))
1253d71ae5a4SJacob Faibussowitsch {
1254d25893d9SBarry Smith   PetscFunctionBegin;
1255d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1256d25893d9SBarry Smith   snes->ops->usercompute = compute;
1257d25893d9SBarry Smith   snes->ops->userdestroy = destroy;
12583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1259d25893d9SBarry Smith }
1260a847f771SSatish Balay 
1261b07ff414SBarry Smith /*@
1262f6dfbefdSBarry Smith   SNESSetApplicationContext - Sets the optional user-defined context for the nonlinear solvers.
12639b94acceSBarry Smith 
1264c3339decSBarry Smith   Logically Collective
1265fee21e36SBarry Smith 
1266c7afd0dbSLois Curfman McInnes   Input Parameters:
1267f6dfbefdSBarry Smith + snes - the `SNES` context
1268c7afd0dbSLois Curfman McInnes - usrP - optional user context
1269c7afd0dbSLois Curfman McInnes 
127036851e7fSLois Curfman McInnes   Level: intermediate
127136851e7fSLois Curfman McInnes 
1272f6dfbefdSBarry Smith   Notes:
1273f6dfbefdSBarry Smith   Users can provide a context when constructing the `SNES` options and then access it inside their function, Jacobian, or other evaluation function
1274f6dfbefdSBarry Smith   with `SNESGetApplicationContext()`
1275f6dfbefdSBarry Smith 
1276f6dfbefdSBarry Smith   To provide a function that computes the context for you use `SNESSetComputeApplicationContext()`
1277f6dfbefdSBarry Smith 
1278420bcc1bSBarry Smith   Fortran Note:
1279dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1280420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1281daf670e6SBarry Smith 
12821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetComputeApplicationContext()`, `SNESGetApplicationContext()`
12839b94acceSBarry Smith @*/
1284d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetApplicationContext(SNES snes, void *usrP)
1285d71ae5a4SJacob Faibussowitsch {
1286b07ff414SBarry Smith   KSP ksp;
12871b2093e4SBarry Smith 
12883a40ed3dSBarry Smith   PetscFunctionBegin;
12890700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
12909566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
12919566063dSJacob Faibussowitsch   PetscCall(KSPSetApplicationContext(ksp, usrP));
12929b94acceSBarry Smith   snes->user = usrP;
12933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12949b94acceSBarry Smith }
129574679c65SBarry Smith 
1296b07ff414SBarry Smith /*@
12979b94acceSBarry Smith   SNESGetApplicationContext - Gets the user-defined context for the
1298420bcc1bSBarry Smith   nonlinear solvers set with `SNESGetApplicationContext()` or `SNESSetComputeApplicationContext()`
12999b94acceSBarry Smith 
1300c7afd0dbSLois Curfman McInnes   Not Collective
1301c7afd0dbSLois Curfman McInnes 
13029b94acceSBarry Smith   Input Parameter:
1303f6dfbefdSBarry Smith . snes - `SNES` context
13049b94acceSBarry Smith 
13059b94acceSBarry Smith   Output Parameter:
13069b94acceSBarry Smith . usrP - user context
13079b94acceSBarry Smith 
130836851e7fSLois Curfman McInnes   Level: intermediate
130936851e7fSLois Curfman McInnes 
1310420bcc1bSBarry Smith   Fortran Note:
1311dc4c0fb0SBarry Smith   You must write a Fortran interface definition for this
1312420bcc1bSBarry Smith   function that tells Fortran the Fortran derived data type that you are passing in as the `usrP` argument.
1313dc4c0fb0SBarry Smith 
1314420bcc1bSBarry Smith .seealso: [](ch_snes), `SNESSetApplicationContext()`, `SNESSetComputeApplicationContext()`
13159b94acceSBarry Smith @*/
1316d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetApplicationContext(SNES snes, void *usrP)
1317d71ae5a4SJacob Faibussowitsch {
13183a40ed3dSBarry Smith   PetscFunctionBegin;
13190700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1320e71120c6SJed Brown   *(void **)usrP = snes->user;
13213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13229b94acceSBarry Smith }
132374679c65SBarry Smith 
13249b94acceSBarry Smith /*@
1325420bcc1bSBarry Smith   SNESSetUseMatrixFree - indicates that `SNES` should use matrix-free finite difference matrix-vector products to apply the Jacobian.
13263565c898SBarry Smith 
1327dc4c0fb0SBarry Smith   Logically Collective
13283565c898SBarry Smith 
13293565c898SBarry Smith   Input Parameters:
1330f6dfbefdSBarry Smith + snes        - `SNES` context
1331f6dfbefdSBarry Smith . mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1332f6dfbefdSBarry 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
1333420bcc1bSBarry Smith                 this option no matrix-element based preconditioners can be used in the linear solve since the matrix won't be explicitly available
13343565c898SBarry Smith 
1335f6dfbefdSBarry Smith   Options Database Keys:
133601c1178eSBarry Smith + -snes_mf_operator - use matrix-free only for the mat operator
1337f6dfbefdSBarry Smith . -snes_mf          - use matrix-free for both the mat and pmat operator
1338ec5066bdSBarry Smith . -snes_fd_color    - compute the Jacobian via coloring and finite differences.
1339ec5066bdSBarry Smith - -snes_fd          - compute the Jacobian via finite differences (slow)
13403565c898SBarry Smith 
13413565c898SBarry Smith   Level: intermediate
13423565c898SBarry Smith 
1343f6dfbefdSBarry Smith   Note:
1344420bcc1bSBarry Smith   `SNES` supports three approaches for computing (approximate) Jacobians: user provided via `SNESSetJacobian()`, matrix-free using `MatCreateSNESMF()`,
1345420bcc1bSBarry Smith   and computing explicitly with
1346f6dfbefdSBarry Smith   finite differences and coloring using `MatFDColoring`. It is also possible to use automatic differentiation and the `MatFDColoring` object.
1347ec5066bdSBarry Smith 
1348420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetUseMatrixFree()`, `MatCreateSNESMF()`, `SNESComputeJacobianDefaultColor()`, `MatFDColoring`
13493565c898SBarry Smith @*/
1350d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUseMatrixFree(SNES snes, PetscBool mf_operator, PetscBool mf)
1351d71ae5a4SJacob Faibussowitsch {
13523565c898SBarry Smith   PetscFunctionBegin;
13533565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
135488b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf_operator, 2);
135588b4c220SStefano Zampini   PetscValidLogicalCollectiveBool(snes, mf, 3);
13564ddffce6SLisandro Dalcin   snes->mf          = mf_operator ? PETSC_TRUE : mf;
13573565c898SBarry Smith   snes->mf_operator = mf_operator;
13583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13593565c898SBarry Smith }
13603565c898SBarry Smith 
13613565c898SBarry Smith /*@
1362dc4c0fb0SBarry Smith   SNESGetUseMatrixFree - indicates if the `SNES` uses matrix-free finite difference matrix vector products to apply the Jacobian.
13633565c898SBarry Smith 
1364420bcc1bSBarry Smith   Not Collective, but the resulting flags will be the same on all MPI processes
13653565c898SBarry Smith 
13663565c898SBarry Smith   Input Parameter:
1367f6dfbefdSBarry Smith . snes - `SNES` context
13683565c898SBarry Smith 
13693565c898SBarry Smith   Output Parameters:
1370f6dfbefdSBarry Smith + mf_operator - use matrix-free only for the Amat used by `SNESSetJacobian()`, this means the user provided Pmat will continue to be used
1371f6dfbefdSBarry 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
13723565c898SBarry Smith 
13733565c898SBarry Smith   Level: intermediate
13743565c898SBarry Smith 
13751cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetUseMatrixFree()`, `MatCreateSNESMF()`
13763565c898SBarry Smith @*/
1377d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUseMatrixFree(SNES snes, PetscBool *mf_operator, PetscBool *mf)
1378d71ae5a4SJacob Faibussowitsch {
13793565c898SBarry Smith   PetscFunctionBegin;
13803565c898SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
13813565c898SBarry Smith   if (mf) *mf = snes->mf;
13823565c898SBarry Smith   if (mf_operator) *mf_operator = snes->mf_operator;
13833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13843565c898SBarry Smith }
13853565c898SBarry Smith 
13863565c898SBarry Smith /*@
1387420bcc1bSBarry Smith   SNESGetIterationNumber - Gets the number of nonlinear iterations completed in the current or most recent `SNESSolve()`
13889b94acceSBarry Smith 
1389c7afd0dbSLois Curfman McInnes   Not Collective
1390c7afd0dbSLois Curfman McInnes 
13919b94acceSBarry Smith   Input Parameter:
1392f6dfbefdSBarry Smith . snes - `SNES` context
13939b94acceSBarry Smith 
13949b94acceSBarry Smith   Output Parameter:
13959b94acceSBarry Smith . iter - iteration number
13969b94acceSBarry Smith 
1397dc4c0fb0SBarry Smith   Level: intermediate
1398dc4c0fb0SBarry Smith 
1399c8228a4eSBarry Smith   Notes:
1400c8228a4eSBarry Smith   For example, during the computation of iteration 2 this would return 1.
1401c8228a4eSBarry Smith 
1402c8228a4eSBarry Smith   This is useful for using lagged Jacobians (where one does not recompute the
1403f6dfbefdSBarry Smith   Jacobian at each `SNES` iteration). For example, the code
140408405cd6SLois Curfman McInnes .vb
140508405cd6SLois Curfman McInnes       ierr = SNESGetIterationNumber(snes,&it);
140608405cd6SLois Curfman McInnes       if (!(it % 2)) {
140708405cd6SLois Curfman McInnes         [compute Jacobian here]
140808405cd6SLois Curfman McInnes       }
140908405cd6SLois Curfman McInnes .ve
1410f6dfbefdSBarry Smith   can be used in your function that computes the Jacobian to cause the Jacobian to be
1411f6dfbefdSBarry Smith   recomputed every second `SNES` iteration. See also `SNESSetLagJacobian()`
1412c8228a4eSBarry Smith 
1413f6dfbefdSBarry Smith   After the `SNES` solve is complete this will return the number of nonlinear iterations used.
1414c04deec6SBarry Smith 
1415420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetLagJacobian()`, `SNESGetLinearSolveIterations()`, `SNESSetMonitor()`
14169b94acceSBarry Smith @*/
1417d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetIterationNumber(SNES snes, PetscInt *iter)
1418d71ae5a4SJacob Faibussowitsch {
14193a40ed3dSBarry Smith   PetscFunctionBegin;
14200700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14214f572ea9SToby Isaac   PetscAssertPointer(iter, 2);
14229b94acceSBarry Smith   *iter = snes->iter;
14233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14249b94acceSBarry Smith }
142574679c65SBarry Smith 
1426360c497dSPeter Brune /*@
1427360c497dSPeter Brune   SNESSetIterationNumber - Sets the current iteration number.
1428360c497dSPeter Brune 
1429360c497dSPeter Brune   Not Collective
1430360c497dSPeter Brune 
1431d8d19677SJose E. Roman   Input Parameters:
1432f6dfbefdSBarry Smith + snes - `SNES` context
1433a2b725a8SWilliam Gropp - iter - iteration number
1434360c497dSPeter Brune 
1435360c497dSPeter Brune   Level: developer
1436360c497dSPeter Brune 
1437420bcc1bSBarry Smith   Note:
1438420bcc1bSBarry Smith   This should only be called inside a `SNES` nonlinear solver.
1439420bcc1bSBarry Smith 
14401cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetLinearSolveIterations()`
1441360c497dSPeter Brune @*/
1442d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetIterationNumber(SNES snes, PetscInt iter)
1443d71ae5a4SJacob Faibussowitsch {
1444360c497dSPeter Brune   PetscFunctionBegin;
1445360c497dSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14469566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsTakeAccess((PetscObject)snes));
1447360c497dSPeter Brune   snes->iter = iter;
14489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsGrantAccess((PetscObject)snes));
14493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1450360c497dSPeter Brune }
1451360c497dSPeter Brune 
14529b94acceSBarry Smith /*@
1453b850b91aSLisandro Dalcin   SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps
1454420bcc1bSBarry Smith   attempted by the nonlinear solver in the current or most recent `SNESSolve()` .
14559b94acceSBarry Smith 
1456c7afd0dbSLois Curfman McInnes   Not Collective
1457c7afd0dbSLois Curfman McInnes 
14589b94acceSBarry Smith   Input Parameter:
1459f6dfbefdSBarry Smith . snes - `SNES` context
14609b94acceSBarry Smith 
14619b94acceSBarry Smith   Output Parameter:
14629b94acceSBarry Smith . nfails - number of unsuccessful steps attempted
14639b94acceSBarry Smith 
1464dc4c0fb0SBarry Smith   Level: intermediate
1465dc4c0fb0SBarry Smith 
1466f6dfbefdSBarry Smith   Note:
1467f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
1468c96a6f78SLois Curfman McInnes 
14691cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1470db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetMaxNonlinearStepFailures()`
14719b94acceSBarry Smith @*/
1472d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNonlinearStepFailures(SNES snes, PetscInt *nfails)
1473d71ae5a4SJacob Faibussowitsch {
14743a40ed3dSBarry Smith   PetscFunctionBegin;
14750700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
14764f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
147750ffb88aSMatthew Knepley   *nfails = snes->numFailures;
14783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147950ffb88aSMatthew Knepley }
148050ffb88aSMatthew Knepley 
148150ffb88aSMatthew Knepley /*@
1482b850b91aSLisandro Dalcin   SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps
1483420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
148450ffb88aSMatthew Knepley 
148550ffb88aSMatthew Knepley   Not Collective
148650ffb88aSMatthew Knepley 
148750ffb88aSMatthew Knepley   Input Parameters:
1488f6dfbefdSBarry Smith + snes     - `SNES` context
148977e5a1f9SBarry Smith - maxFails - maximum of unsuccessful steps allowed, use `PETSC_UNLIMITED` to have no limit on the number of failures
149050ffb88aSMatthew Knepley 
1491420bcc1bSBarry Smith   Options Database Key:
1492420bcc1bSBarry Smith . -snes_max_fail <n> - maximum number of unsuccessful steps allowed
1493420bcc1bSBarry Smith 
149450ffb88aSMatthew Knepley   Level: intermediate
149550ffb88aSMatthew Knepley 
1496420bcc1bSBarry Smith   Developer Note:
1497420bcc1bSBarry Smith   The options database key is wrong for this function name
1498420bcc1bSBarry Smith 
14991cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1500db781477SPatrick Sanan           `SNESGetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
150150ffb88aSMatthew Knepley @*/
1502d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails)
1503d71ae5a4SJacob Faibussowitsch {
150450ffb88aSMatthew Knepley   PetscFunctionBegin;
15050700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
150677e5a1f9SBarry Smith 
150777e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
15081690c2aeSBarry Smith     snes->maxFailures = PETSC_INT_MAX;
150977e5a1f9SBarry Smith   } else {
151077e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
151150ffb88aSMatthew Knepley     snes->maxFailures = maxFails;
151277e5a1f9SBarry Smith   }
15133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
151450ffb88aSMatthew Knepley }
151550ffb88aSMatthew Knepley 
151650ffb88aSMatthew Knepley /*@
1517b850b91aSLisandro Dalcin   SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps
1518420bcc1bSBarry Smith   attempted by the nonlinear solver before it gives up and returns unconverged or generates an error
151950ffb88aSMatthew Knepley 
152050ffb88aSMatthew Knepley   Not Collective
152150ffb88aSMatthew Knepley 
152250ffb88aSMatthew Knepley   Input Parameter:
152320f4b53cSBarry Smith . snes - `SNES` context
152450ffb88aSMatthew Knepley 
152550ffb88aSMatthew Knepley   Output Parameter:
152650ffb88aSMatthew Knepley . maxFails - maximum of unsuccessful steps
152750ffb88aSMatthew Knepley 
152850ffb88aSMatthew Knepley   Level: intermediate
152950ffb88aSMatthew Knepley 
15301cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`,
1531db781477SPatrick Sanan           `SNESSetMaxNonlinearStepFailures()`, `SNESGetNonlinearStepFailures()`
153250ffb88aSMatthew Knepley @*/
1533d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails)
1534d71ae5a4SJacob Faibussowitsch {
153550ffb88aSMatthew Knepley   PetscFunctionBegin;
15360700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15374f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
153850ffb88aSMatthew Knepley   *maxFails = snes->maxFailures;
15393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15409b94acceSBarry Smith }
1541a847f771SSatish Balay 
15422541af92SBarry Smith /*@
15432541af92SBarry Smith   SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations
1544420bcc1bSBarry Smith   done by the `SNES` object in the current or most recent `SNESSolve()`
15452541af92SBarry Smith 
15462541af92SBarry Smith   Not Collective
15472541af92SBarry Smith 
15482541af92SBarry Smith   Input Parameter:
1549f6dfbefdSBarry Smith . snes - `SNES` context
15502541af92SBarry Smith 
15512541af92SBarry Smith   Output Parameter:
15522541af92SBarry Smith . nfuncs - number of evaluations
15532541af92SBarry Smith 
15542541af92SBarry Smith   Level: intermediate
15552541af92SBarry Smith 
1556f6dfbefdSBarry Smith   Note:
1557f6dfbefdSBarry Smith   Reset every time `SNESSolve()` is called unless `SNESSetCountersReset()` is used.
1558971e163fSPeter Brune 
15591cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`, `SNESGetLinearSolveFailures()`, `SNESSetCountersReset()`
15602541af92SBarry Smith @*/
1561d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs)
1562d71ae5a4SJacob Faibussowitsch {
15632541af92SBarry Smith   PetscFunctionBegin;
15640700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15654f572ea9SToby Isaac   PetscAssertPointer(nfuncs, 2);
15662541af92SBarry Smith   *nfuncs = snes->nfuncs;
15673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15682541af92SBarry Smith }
15692541af92SBarry Smith 
15703d4c4710SBarry Smith /*@
15713d4c4710SBarry Smith   SNESGetLinearSolveFailures - Gets the number of failed (non-converged)
1572420bcc1bSBarry Smith   linear solvers in the current or most recent `SNESSolve()`
15733d4c4710SBarry Smith 
15743d4c4710SBarry Smith   Not Collective
15753d4c4710SBarry Smith 
15763d4c4710SBarry Smith   Input Parameter:
1577f6dfbefdSBarry Smith . snes - `SNES` context
15783d4c4710SBarry Smith 
15793d4c4710SBarry Smith   Output Parameter:
15803d4c4710SBarry Smith . nfails - number of failed solves
15813d4c4710SBarry Smith 
1582f6dfbefdSBarry Smith   Options Database Key:
15839d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
15849d85da0cSMatthew G. Knepley 
1585f6dfbefdSBarry Smith   Level: intermediate
1586f6dfbefdSBarry Smith 
1587f6dfbefdSBarry Smith   Note:
1588f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()`.
15893d4c4710SBarry Smith 
15901cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`
15913d4c4710SBarry Smith @*/
1592d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveFailures(SNES snes, PetscInt *nfails)
1593d71ae5a4SJacob Faibussowitsch {
15943d4c4710SBarry Smith   PetscFunctionBegin;
15950700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
15964f572ea9SToby Isaac   PetscAssertPointer(nfails, 2);
15973d4c4710SBarry Smith   *nfails = snes->numLinearSolveFailures;
15983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15993d4c4710SBarry Smith }
16003d4c4710SBarry Smith 
16013d4c4710SBarry Smith /*@
16023d4c4710SBarry Smith   SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts
1603f6dfbefdSBarry Smith   allowed before `SNES` returns with a diverged reason of `SNES_DIVERGED_LINEAR_SOLVE`
16043d4c4710SBarry Smith 
1605c3339decSBarry Smith   Logically Collective
16063d4c4710SBarry Smith 
16073d4c4710SBarry Smith   Input Parameters:
1608f6dfbefdSBarry Smith + snes     - `SNES` context
160977e5a1f9SBarry Smith - maxFails - maximum allowed linear solve failures, use `PETSC_UNLIMITED` to have no limit on the number of failures
16103d4c4710SBarry Smith 
1611f6dfbefdSBarry Smith   Options Database Key:
16129d85da0cSMatthew G. Knepley . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated
16139d85da0cSMatthew G. Knepley 
1614dc4c0fb0SBarry Smith   Level: intermediate
1615dc4c0fb0SBarry Smith 
1616f6dfbefdSBarry Smith   Note:
1617f6dfbefdSBarry Smith   By default this is 0; that is `SNES` returns on the first failed linear solve
16183d4c4710SBarry Smith 
1619420bcc1bSBarry Smith   Developer Note:
1620420bcc1bSBarry Smith   The options database key is wrong for this function name
1621420bcc1bSBarry Smith 
16221cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESGetLinearSolveIterations()`
16233d4c4710SBarry Smith @*/
1624d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails)
1625d71ae5a4SJacob Faibussowitsch {
16263d4c4710SBarry Smith   PetscFunctionBegin;
16270700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1628c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxFails, 2);
162977e5a1f9SBarry Smith 
163077e5a1f9SBarry Smith   if (maxFails == PETSC_UNLIMITED) {
16311690c2aeSBarry Smith     snes->maxLinearSolveFailures = PETSC_INT_MAX;
163277e5a1f9SBarry Smith   } else {
163377e5a1f9SBarry Smith     PetscCheck(maxFails >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
16343d4c4710SBarry Smith     snes->maxLinearSolveFailures = maxFails;
163577e5a1f9SBarry Smith   }
16363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16373d4c4710SBarry Smith }
16383d4c4710SBarry Smith 
16393d4c4710SBarry Smith /*@
16403d4c4710SBarry Smith   SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that
1641f6dfbefdSBarry Smith   are allowed before `SNES` returns as unsuccessful
16423d4c4710SBarry Smith 
16433d4c4710SBarry Smith   Not Collective
16443d4c4710SBarry Smith 
16453d4c4710SBarry Smith   Input Parameter:
1646f6dfbefdSBarry Smith . snes - `SNES` context
16473d4c4710SBarry Smith 
16483d4c4710SBarry Smith   Output Parameter:
16493d4c4710SBarry Smith . maxFails - maximum of unsuccessful solves allowed
16503d4c4710SBarry Smith 
16513d4c4710SBarry Smith   Level: intermediate
16523d4c4710SBarry Smith 
1653f6dfbefdSBarry Smith   Note:
1654f6dfbefdSBarry Smith   By default this is 1; that is `SNES` returns on the first failed linear solve
16553d4c4710SBarry Smith 
16561cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetErrorIfNotConverged()`, `SNESGetLinearSolveFailures()`, `SNESGetLinearSolveIterations()`, `SNESSetMaxLinearSolveFailures()`,
16573d4c4710SBarry Smith @*/
1658d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails)
1659d71ae5a4SJacob Faibussowitsch {
16603d4c4710SBarry Smith   PetscFunctionBegin;
16610700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16624f572ea9SToby Isaac   PetscAssertPointer(maxFails, 2);
16633d4c4710SBarry Smith   *maxFails = snes->maxLinearSolveFailures;
16643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16653d4c4710SBarry Smith }
16663d4c4710SBarry Smith 
1667c96a6f78SLois Curfman McInnes /*@
1668b850b91aSLisandro Dalcin   SNESGetLinearSolveIterations - Gets the total number of linear iterations
1669420bcc1bSBarry Smith   used by the nonlinear solver in the most recent `SNESSolve()`
1670c96a6f78SLois Curfman McInnes 
1671c7afd0dbSLois Curfman McInnes   Not Collective
1672c7afd0dbSLois Curfman McInnes 
1673c96a6f78SLois Curfman McInnes   Input Parameter:
1674f6dfbefdSBarry Smith . snes - `SNES` context
1675c96a6f78SLois Curfman McInnes 
1676c96a6f78SLois Curfman McInnes   Output Parameter:
1677c96a6f78SLois Curfman McInnes . lits - number of linear iterations
1678c96a6f78SLois Curfman McInnes 
1679dc4c0fb0SBarry Smith   Level: intermediate
1680dc4c0fb0SBarry Smith 
1681c96a6f78SLois Curfman McInnes   Notes:
1682f6dfbefdSBarry Smith   This counter is reset to zero for each successive call to `SNESSolve()` unless `SNESSetCountersReset()` is used.
1683c96a6f78SLois Curfman McInnes 
1684f6dfbefdSBarry 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
1685f6dfbefdSBarry Smith   then call `KSPGetIterationNumber()` after the failed solve.
1686010be392SBarry Smith 
16871cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetIterationNumber()`, `SNESGetLinearSolveFailures()`, `SNESGetMaxLinearSolveFailures()`, `SNESSetCountersReset()`
1688c96a6f78SLois Curfman McInnes @*/
1689d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLinearSolveIterations(SNES snes, PetscInt *lits)
1690d71ae5a4SJacob Faibussowitsch {
16913a40ed3dSBarry Smith   PetscFunctionBegin;
16920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
16934f572ea9SToby Isaac   PetscAssertPointer(lits, 2);
1694c96a6f78SLois Curfman McInnes   *lits = snes->linear_its;
16953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1696c96a6f78SLois Curfman McInnes }
1697c96a6f78SLois Curfman McInnes 
1698971e163fSPeter Brune /*@
1699971e163fSPeter Brune   SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations
1700f6dfbefdSBarry Smith   are reset every time `SNESSolve()` is called.
1701971e163fSPeter Brune 
1702c3339decSBarry Smith   Logically Collective
1703971e163fSPeter Brune 
1704d8d19677SJose E. Roman   Input Parameters:
1705f6dfbefdSBarry Smith + snes  - `SNES` context
1706f6dfbefdSBarry Smith - reset - whether to reset the counters or not, defaults to `PETSC_TRUE`
1707971e163fSPeter Brune 
1708971e163fSPeter Brune   Level: developer
1709971e163fSPeter Brune 
17101cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
1711971e163fSPeter Brune @*/
1712d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetCountersReset(SNES snes, PetscBool reset)
1713d71ae5a4SJacob Faibussowitsch {
1714971e163fSPeter Brune   PetscFunctionBegin;
1715971e163fSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1716971e163fSPeter Brune   PetscValidLogicalCollectiveBool(snes, reset, 2);
1717971e163fSPeter Brune   snes->counters_reset = reset;
17183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1719971e163fSPeter Brune }
1720971e163fSPeter Brune 
17212999313aSBarry Smith /*@
172212b1dd1aSStefano Zampini   SNESResetCounters - Reset counters for linear iterations and function evaluations.
172312b1dd1aSStefano Zampini 
172412b1dd1aSStefano Zampini   Logically Collective
172512b1dd1aSStefano Zampini 
172612b1dd1aSStefano Zampini   Input Parameters:
172712b1dd1aSStefano Zampini . snes - `SNES` context
172812b1dd1aSStefano Zampini 
172912b1dd1aSStefano Zampini   Level: developer
173012b1dd1aSStefano Zampini 
173112b1dd1aSStefano Zampini   Note:
173212b1dd1aSStefano Zampini   It honors the flag set with `SNESSetCountersReset()`
173312b1dd1aSStefano Zampini 
173412b1dd1aSStefano Zampini .seealso: [](ch_snes), `SNESGetNumberFunctionEvals()`, `SNESGetLinearSolveIterations()`, `SNESGetNPC()`
173512b1dd1aSStefano Zampini @*/
173612b1dd1aSStefano Zampini PetscErrorCode SNESResetCounters(SNES snes)
173712b1dd1aSStefano Zampini {
173812b1dd1aSStefano Zampini   PetscFunctionBegin;
173912b1dd1aSStefano Zampini   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
174012b1dd1aSStefano Zampini   if (snes->counters_reset) {
174112b1dd1aSStefano Zampini     snes->nfuncs      = 0;
174212b1dd1aSStefano Zampini     snes->linear_its  = 0;
174312b1dd1aSStefano Zampini     snes->numFailures = 0;
174412b1dd1aSStefano Zampini   }
174512b1dd1aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
174612b1dd1aSStefano Zampini }
174712b1dd1aSStefano Zampini 
174812b1dd1aSStefano Zampini /*@
1749f6dfbefdSBarry Smith   SNESSetKSP - Sets a `KSP` context for the `SNES` object to use
17502999313aSBarry Smith 
1751420bcc1bSBarry Smith   Not Collective, but the `SNES` and `KSP` objects must live on the same `MPI_Comm`
17522999313aSBarry Smith 
17532999313aSBarry Smith   Input Parameters:
1754f6dfbefdSBarry Smith + snes - the `SNES` context
1755f6dfbefdSBarry Smith - ksp  - the `KSP` context
17562999313aSBarry Smith 
1757dc4c0fb0SBarry Smith   Level: developer
1758dc4c0fb0SBarry Smith 
17592999313aSBarry Smith   Notes:
1760f6dfbefdSBarry Smith   The `SNES` object already has its `KSP` object, you can obtain with `SNESGetKSP()`
17612999313aSBarry Smith   so this routine is rarely needed.
17622999313aSBarry Smith 
1763f6dfbefdSBarry Smith   The `KSP` object that is already in the `SNES` object has its reference count
1764420bcc1bSBarry Smith   decreased by one when this is called.
17652999313aSBarry Smith 
176642747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `KSP`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`
17672999313aSBarry Smith @*/
1768d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetKSP(SNES snes, KSP ksp)
1769d71ae5a4SJacob Faibussowitsch {
17702999313aSBarry Smith   PetscFunctionBegin;
17710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
17720700a824SBarry Smith   PetscValidHeaderSpecific(ksp, KSP_CLASSID, 2);
17732999313aSBarry Smith   PetscCheckSameComm(snes, 1, ksp, 2);
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ksp));
17759566063dSJacob Faibussowitsch   if (snes->ksp) PetscCall(PetscObjectDereference((PetscObject)snes->ksp));
17762999313aSBarry Smith   snes->ksp = ksp;
17773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17782999313aSBarry Smith }
17792999313aSBarry Smith 
178052baeb72SSatish Balay /*@
178177e5a1f9SBarry Smith   SNESParametersInitialize - Sets all the parameters in `snes` to their default value (when `SNESCreate()` was called) if they
178277e5a1f9SBarry Smith   currently contain default values
178377e5a1f9SBarry Smith 
178477e5a1f9SBarry Smith   Collective
178577e5a1f9SBarry Smith 
178677e5a1f9SBarry Smith   Input Parameter:
178777e5a1f9SBarry Smith . snes - the `SNES` object
178877e5a1f9SBarry Smith 
178977e5a1f9SBarry Smith   Level: developer
179077e5a1f9SBarry Smith 
179177e5a1f9SBarry Smith   Developer Note:
179277e5a1f9SBarry Smith   This is called by all the `SNESCreate_XXX()` routines.
179377e5a1f9SBarry Smith 
179477e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`,
179577e5a1f9SBarry Smith           `PetscObjectParameterSetDefault()`
179677e5a1f9SBarry Smith @*/
179777e5a1f9SBarry Smith PetscErrorCode SNESParametersInitialize(SNES snes)
179877e5a1f9SBarry Smith {
179977e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_its, 50);
180077e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, max_funcs, 10000);
180177e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, rtol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
180277e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, abstol, PetscDefined(USE_REAL_SINGLE) ? 1.e-25 : 1.e-50);
180377e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, stol, PetscDefined(USE_REAL_SINGLE) ? 1.e-5 : 1.e-8);
180477e5a1f9SBarry Smith   PetscObjectParameterSetDefault(snes, divtol, 1.e4);
180577e5a1f9SBarry Smith   return PETSC_SUCCESS;
180677e5a1f9SBarry Smith }
180777e5a1f9SBarry Smith 
180877e5a1f9SBarry Smith /*@
1809dc4c0fb0SBarry Smith   SNESCreate - Creates a nonlinear solver context used to manage a set of nonlinear solves
18109b94acceSBarry Smith 
1811d083f849SBarry Smith   Collective
1812c7afd0dbSLois Curfman McInnes 
1813f6dfbefdSBarry Smith   Input Parameter:
1814906ed7ccSBarry Smith . comm - MPI communicator
18159b94acceSBarry Smith 
18169b94acceSBarry Smith   Output Parameter:
181720f4b53cSBarry Smith . outsnes - the new `SNES` context
18189b94acceSBarry Smith 
1819c7afd0dbSLois Curfman McInnes   Options Database Keys:
1820dc4c0fb0SBarry Smith + -snes_mf          - Activates default matrix-free Jacobian-vector products, and no preconditioning matrix
1821dc4c0fb0SBarry Smith . -snes_mf_operator - Activates default matrix-free Jacobian-vector products, and a user-provided preconditioning matrix
1822dc4c0fb0SBarry Smith                       as set by `SNESSetJacobian()`
1823dc4c0fb0SBarry Smith . -snes_fd_coloring - uses a relative fast computation of the Jacobian using finite differences and a graph coloring
1824c7afd0dbSLois Curfman McInnes - -snes_fd          - Uses (slow!) finite differences to compute Jacobian
1825c1f60f51SBarry Smith 
182636851e7fSLois Curfman McInnes   Level: beginner
182736851e7fSLois Curfman McInnes 
182895452b02SPatrick Sanan   Developer Notes:
1829f6dfbefdSBarry Smith   `SNES` always creates a `KSP` object even though many `SNES` methods do not use it. This is
1830efd4aadfSBarry Smith   unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the
1831f6dfbefdSBarry Smith   particular method does use `KSP` and regulates if the information about the `KSP` is printed
1832f6dfbefdSBarry Smith   in `SNESView()`.
1833efd4aadfSBarry Smith 
1834f6dfbefdSBarry Smith   `TSSetFromOptions()` does call `SNESSetFromOptions()` which can lead to users being confused
1835f6dfbefdSBarry Smith   by help messages about meaningless `SNES` options.
1836f6dfbefdSBarry Smith 
1837dc4c0fb0SBarry Smith   `SNES` always creates the snes->kspconvctx even though it is used by only one type. This should be fixed.
1838efd4aadfSBarry Smith 
1839e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESDestroy()`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
18409b94acceSBarry Smith @*/
1841d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESCreate(MPI_Comm comm, SNES *outsnes)
1842d71ae5a4SJacob Faibussowitsch {
18439b94acceSBarry Smith   SNES       snes;
1844fa9f3622SBarry Smith   SNESKSPEW *kctx;
184537fcc0dbSBarry Smith 
18463a40ed3dSBarry Smith   PetscFunctionBegin;
18474f572ea9SToby Isaac   PetscAssertPointer(outsnes, 2);
18489566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
18498ba1e511SMatthew Knepley 
18509566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(snes, SNES_CLASSID, "SNES", "Nonlinear solver", "SNES", comm, SNESDestroy, SNESView));
18518d359177SBarry Smith   snes->ops->converged = SNESConvergedDefault;
18522c155ee1SBarry Smith   snes->usesksp        = PETSC_TRUE;
18539b94acceSBarry Smith   snes->norm           = 0.0;
1854c1e67a49SFande Kong   snes->xnorm          = 0.0;
1855c1e67a49SFande Kong   snes->ynorm          = 0.0;
1856365a6726SPeter Brune   snes->normschedule   = SNES_NORM_ALWAYS;
18576c67d002SPeter Brune   snes->functype       = SNES_FUNCTION_DEFAULT;
1858b4874afaSBarry Smith   snes->ttol           = 0.0;
185977e5a1f9SBarry Smith 
1860e37c518bSBarry Smith   snes->rnorm0               = 0;
18619b94acceSBarry Smith   snes->nfuncs               = 0;
186250ffb88aSMatthew Knepley   snes->numFailures          = 0;
186350ffb88aSMatthew Knepley   snes->maxFailures          = 1;
18647a00f4a9SLois Curfman McInnes   snes->linear_its           = 0;
1865e35cf81dSBarry Smith   snes->lagjacobian          = 1;
186637ec4e1aSPeter Brune   snes->jac_iter             = 0;
186737ec4e1aSPeter Brune   snes->lagjac_persist       = PETSC_FALSE;
1868a8054027SBarry Smith   snes->lagpreconditioner    = 1;
186937ec4e1aSPeter Brune   snes->pre_iter             = 0;
187037ec4e1aSPeter Brune   snes->lagpre_persist       = PETSC_FALSE;
1871639f9d9dSBarry Smith   snes->numbermonitors       = 0;
1872c4421ceaSFande Kong   snes->numberreasonviews    = 0;
18739e5d0892SLisandro Dalcin   snes->data                 = NULL;
18744dc4c822SBarry Smith   snes->setupcalled          = PETSC_FALSE;
1875186905e3SBarry Smith   snes->ksp_ewconv           = PETSC_FALSE;
18766f24a144SLois Curfman McInnes   snes->nwork                = 0;
18779e5d0892SLisandro Dalcin   snes->work                 = NULL;
187858c9b817SLisandro Dalcin   snes->nvwork               = 0;
18799e5d0892SLisandro Dalcin   snes->vwork                = NULL;
1880758f92a0SBarry Smith   snes->conv_hist_len        = 0;
1881758f92a0SBarry Smith   snes->conv_hist_max        = 0;
18820298fd71SBarry Smith   snes->conv_hist            = NULL;
18830298fd71SBarry Smith   snes->conv_hist_its        = NULL;
1884758f92a0SBarry Smith   snes->conv_hist_reset      = PETSC_TRUE;
1885971e163fSPeter Brune   snes->counters_reset       = PETSC_TRUE;
1886e4ed7901SPeter Brune   snes->vec_func_init_set    = PETSC_FALSE;
1887184914b5SBarry Smith   snes->reason               = SNES_CONVERGED_ITERATING;
1888efd4aadfSBarry Smith   snes->npcside              = PC_RIGHT;
1889b3cd9a81SMatthew G. Knepley   snes->setfromoptionscalled = 0;
1890c40d0f55SPeter Brune 
1891d8f46077SPeter Brune   snes->mf          = PETSC_FALSE;
1892d8f46077SPeter Brune   snes->mf_operator = PETSC_FALSE;
1893d8f46077SPeter Brune   snes->mf_version  = 1;
1894d8f46077SPeter Brune 
18953d4c4710SBarry Smith   snes->numLinearSolveFailures = 0;
18963d4c4710SBarry Smith   snes->maxLinearSolveFailures = 1;
18973d4c4710SBarry Smith 
1898349187a7SBarry Smith   snes->vizerotolerance     = 1.e-8;
189976bd3646SJed Brown   snes->checkjacdomainerror = PetscDefined(USE_DEBUG) ? PETSC_TRUE : PETSC_FALSE;
1900349187a7SBarry Smith 
19014fc747eaSLawrence Mitchell   /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */
19024fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
19034fc747eaSLawrence Mitchell 
19049b94acceSBarry Smith   /* Create context to compute Eisenstat-Walker relative tolerance for KSP */
19054dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&kctx));
1906f5af7f23SKarl Rupp 
19079b94acceSBarry Smith   snes->kspconvctx  = (void *)kctx;
19089b94acceSBarry Smith   kctx->version     = 2;
19090f0abf79SStefano Zampini   kctx->rtol_0      = 0.3; /* Eisenstat and Walker suggest rtol_0=.5, but
19109b94acceSBarry Smith                              this was too large for some test cases */
191175567043SBarry Smith   kctx->rtol_last   = 0.0;
19120f0abf79SStefano Zampini   kctx->rtol_max    = 0.9;
19139b94acceSBarry Smith   kctx->gamma       = 1.0;
19140f0abf79SStefano Zampini   kctx->alpha       = 0.5 * (1.0 + PetscSqrtReal(5.0));
191571f87433Sdalcinl   kctx->alpha2      = kctx->alpha;
19160f0abf79SStefano Zampini   kctx->threshold   = 0.1;
191775567043SBarry Smith   kctx->lresid_last = 0.0;
191875567043SBarry Smith   kctx->norm_last   = 0.0;
19199b94acceSBarry Smith 
19200f0abf79SStefano Zampini   kctx->rk_last     = 0.0;
19210f0abf79SStefano Zampini   kctx->rk_last_2   = 0.0;
19220f0abf79SStefano Zampini   kctx->rtol_last_2 = 0.0;
19230f0abf79SStefano Zampini   kctx->v4_p1       = 0.1;
19240f0abf79SStefano Zampini   kctx->v4_p2       = 0.4;
19250f0abf79SStefano Zampini   kctx->v4_p3       = 0.7;
19260f0abf79SStefano Zampini   kctx->v4_m1       = 0.8;
19270f0abf79SStefano Zampini   kctx->v4_m2       = 0.5;
19280f0abf79SStefano Zampini   kctx->v4_m3       = 0.1;
19290f0abf79SStefano Zampini   kctx->v4_m4       = 0.5;
19300f0abf79SStefano Zampini 
1931b50c806fSBarry Smith   PetscCall(SNESParametersInitialize(snes));
19329b94acceSBarry Smith   *outsnes = snes;
19333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19349b94acceSBarry Smith }
19359b94acceSBarry Smith 
19369b94acceSBarry Smith /*@C
19379b94acceSBarry Smith   SNESSetFunction - Sets the function evaluation routine and function
1938f6dfbefdSBarry Smith   vector for use by the `SNES` routines in solving systems of nonlinear
19399b94acceSBarry Smith   equations.
19409b94acceSBarry Smith 
1941c3339decSBarry Smith   Logically Collective
1942fee21e36SBarry Smith 
1943c7afd0dbSLois Curfman McInnes   Input Parameters:
1944f6dfbefdSBarry Smith + snes - the `SNES` context
1945dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
19468434afd1SBarry Smith . f    - function evaluation routine;  for calling sequence see `SNESFunctionFn`
1947c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
1948dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
19499b94acceSBarry Smith 
195036851e7fSLois Curfman McInnes   Level: beginner
195136851e7fSLois Curfman McInnes 
19528434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetPicard()`, `SNESFunctionFn`
19539b94acceSBarry Smith @*/
19548434afd1SBarry Smith PetscErrorCode SNESSetFunction(SNES snes, Vec r, SNESFunctionFn *f, void *ctx)
1955d71ae5a4SJacob Faibussowitsch {
19566cab3a1bSJed Brown   DM dm;
19576cab3a1bSJed Brown 
19583a40ed3dSBarry Smith   PetscFunctionBegin;
19590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1960d2a683ecSLisandro Dalcin   if (r) {
1961d2a683ecSLisandro Dalcin     PetscValidHeaderSpecific(r, VEC_CLASSID, 2);
1962d2a683ecSLisandro Dalcin     PetscCheckSameComm(snes, 1, r, 2);
19639566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)r));
19649566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_func));
196585385478SLisandro Dalcin     snes->vec_func = r;
1966d2a683ecSLisandro Dalcin   }
19679566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
19689566063dSJacob Faibussowitsch   PetscCall(DMSNESSetFunction(dm, f, ctx));
196948a46eb9SPierre Jolivet   if (f == SNESPicardComputeFunction) PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
19703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19719b94acceSBarry Smith }
19729b94acceSBarry Smith 
1973e4ed7901SPeter Brune /*@C
19740b4db180SJacob Faibussowitsch   SNESSetInitialFunction - Set an already computed function evaluation at the initial guess to be reused by `SNESSolve()`.
1975e4ed7901SPeter Brune 
1976c3339decSBarry Smith   Logically Collective
1977e4ed7901SPeter Brune 
1978e4ed7901SPeter Brune   Input Parameters:
1979f6dfbefdSBarry Smith + snes - the `SNES` context
1980e4ed7901SPeter Brune - f    - vector to store function value
1981e4ed7901SPeter Brune 
1982dc4c0fb0SBarry Smith   Level: developer
1983dc4c0fb0SBarry Smith 
1984e4ed7901SPeter Brune   Notes:
1985e4ed7901SPeter Brune   This should not be modified during the solution procedure.
1986e4ed7901SPeter Brune 
1987f6dfbefdSBarry Smith   This is used extensively in the `SNESFAS` hierarchy and in nonlinear preconditioning.
1988e4ed7901SPeter Brune 
19891cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFAS`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetInitialFunctionNorm()`
1990e4ed7901SPeter Brune @*/
1991d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f)
1992d71ae5a4SJacob Faibussowitsch {
1993e4ed7901SPeter Brune   Vec vec_func;
1994e4ed7901SPeter Brune 
1995e4ed7901SPeter Brune   PetscFunctionBegin;
1996e4ed7901SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
1997e4ed7901SPeter Brune   PetscValidHeaderSpecific(f, VEC_CLASSID, 2);
1998e4ed7901SPeter Brune   PetscCheckSameComm(snes, 1, f, 2);
1999efd4aadfSBarry Smith   if (snes->npcside == PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) {
2000902f982fSPeter Brune     snes->vec_func_init_set = PETSC_FALSE;
20013ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2002902f982fSPeter Brune   }
20039566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &vec_func, NULL, NULL));
20049566063dSJacob Faibussowitsch   PetscCall(VecCopy(f, vec_func));
2005f5af7f23SKarl Rupp 
2006217b9c2eSPeter Brune   snes->vec_func_init_set = PETSC_TRUE;
20073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2008e4ed7901SPeter Brune }
2009e4ed7901SPeter Brune 
2010534ebe21SPeter Brune /*@
2011f6dfbefdSBarry Smith   SNESSetNormSchedule - Sets the `SNESNormSchedule` used in convergence and monitoring
2012f6dfbefdSBarry Smith   of the `SNES` method, when norms are computed in the solving process
2013534ebe21SPeter Brune 
2014c3339decSBarry Smith   Logically Collective
2015534ebe21SPeter Brune 
2016534ebe21SPeter Brune   Input Parameters:
2017f6dfbefdSBarry Smith + snes         - the `SNES` context
2018365a6726SPeter Brune - normschedule - the frequency of norm computation
2019534ebe21SPeter Brune 
2020517f1916SMatthew G. Knepley   Options Database Key:
202167b8a455SSatish Balay . -snes_norm_schedule <none, always, initialonly, finalonly, initialfinalonly> - set the schedule
2022517f1916SMatthew G. Knepley 
2023dc4c0fb0SBarry Smith   Level: advanced
2024dc4c0fb0SBarry Smith 
2025534ebe21SPeter Brune   Notes:
2026f6dfbefdSBarry Smith   Only certain `SNES` methods support certain `SNESNormSchedules`.  Most require evaluation
2027534ebe21SPeter Brune   of the nonlinear function and the taking of its norm at every iteration to
2028534ebe21SPeter Brune   even ensure convergence at all.  However, methods such as custom Gauss-Seidel methods
2029f6dfbefdSBarry Smith   `SNESNGS` and the like do not require the norm of the function to be computed, and therefore
2030534ebe21SPeter Brune   may either be monitored for convergence or not.  As these are often used as nonlinear
2031534ebe21SPeter Brune   preconditioners, monitoring the norm of their error is not a useful enterprise within
2032534ebe21SPeter Brune   their solution.
2033534ebe21SPeter Brune 
2034e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNESNormSchedule`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`
2035534ebe21SPeter Brune @*/
2036d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule)
2037d71ae5a4SJacob Faibussowitsch {
2038534ebe21SPeter Brune   PetscFunctionBegin;
2039534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2040365a6726SPeter Brune   snes->normschedule = normschedule;
20413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2042534ebe21SPeter Brune }
2043534ebe21SPeter Brune 
2044534ebe21SPeter Brune /*@
2045f6dfbefdSBarry Smith   SNESGetNormSchedule - Gets the `SNESNormSchedule` used in convergence and monitoring
2046f6dfbefdSBarry Smith   of the `SNES` method.
2047534ebe21SPeter Brune 
2048c3339decSBarry Smith   Logically Collective
2049534ebe21SPeter Brune 
2050534ebe21SPeter Brune   Input Parameters:
2051f6dfbefdSBarry Smith + snes         - the `SNES` context
2052365a6726SPeter Brune - normschedule - the type of the norm used
2053534ebe21SPeter Brune 
2054534ebe21SPeter Brune   Level: advanced
2055534ebe21SPeter Brune 
20561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2057534ebe21SPeter Brune @*/
2058d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule)
2059d71ae5a4SJacob Faibussowitsch {
2060534ebe21SPeter Brune   PetscFunctionBegin;
2061534ebe21SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2062365a6726SPeter Brune   *normschedule = snes->normschedule;
20633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2064534ebe21SPeter Brune }
2065534ebe21SPeter Brune 
2066c5ce4427SMatthew G. Knepley /*@
2067c5ce4427SMatthew G. Knepley   SNESSetFunctionNorm - Sets the last computed residual norm.
2068c5ce4427SMatthew G. Knepley 
2069c3339decSBarry Smith   Logically Collective
2070c5ce4427SMatthew G. Knepley 
2071c5ce4427SMatthew G. Knepley   Input Parameters:
2072f6dfbefdSBarry Smith + snes - the `SNES` context
2073f6dfbefdSBarry Smith - norm - the value of the norm
2074c5ce4427SMatthew G. Knepley 
2075c5ce4427SMatthew G. Knepley   Level: developer
2076c5ce4427SMatthew G. Knepley 
20771cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2078c5ce4427SMatthew G. Knepley @*/
2079d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm)
2080d71ae5a4SJacob Faibussowitsch {
2081c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2082c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2083c5ce4427SMatthew G. Knepley   snes->norm = norm;
20843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2085c5ce4427SMatthew G. Knepley }
2086c5ce4427SMatthew G. Knepley 
2087c5ce4427SMatthew G. Knepley /*@
2088c5ce4427SMatthew G. Knepley   SNESGetFunctionNorm - Gets the last computed norm of the residual
2089c5ce4427SMatthew G. Knepley 
2090c5ce4427SMatthew G. Knepley   Not Collective
2091c5ce4427SMatthew G. Knepley 
2092c5ce4427SMatthew G. Knepley   Input Parameter:
2093f6dfbefdSBarry Smith . snes - the `SNES` context
2094c5ce4427SMatthew G. Knepley 
2095c5ce4427SMatthew G. Knepley   Output Parameter:
2096c5ce4427SMatthew G. Knepley . norm - the last computed residual norm
2097c5ce4427SMatthew G. Knepley 
2098c5ce4427SMatthew G. Knepley   Level: developer
2099c5ce4427SMatthew G. Knepley 
21001cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
2101c5ce4427SMatthew G. Knepley @*/
2102d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm)
2103d71ae5a4SJacob Faibussowitsch {
2104c5ce4427SMatthew G. Knepley   PetscFunctionBegin;
2105c5ce4427SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21064f572ea9SToby Isaac   PetscAssertPointer(norm, 2);
2107c5ce4427SMatthew G. Knepley   *norm = snes->norm;
21083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2109c5ce4427SMatthew G. Knepley }
2110c5ce4427SMatthew G. Knepley 
2111c1e67a49SFande Kong /*@
2112f6dfbefdSBarry Smith   SNESGetUpdateNorm - Gets the last computed norm of the solution update
2113c1e67a49SFande Kong 
2114c1e67a49SFande Kong   Not Collective
2115c1e67a49SFande Kong 
2116c1e67a49SFande Kong   Input Parameter:
2117f6dfbefdSBarry Smith . snes - the `SNES` context
2118c1e67a49SFande Kong 
2119c1e67a49SFande Kong   Output Parameter:
2120c1e67a49SFande Kong . ynorm - the last computed update norm
2121c1e67a49SFande Kong 
2122c1e67a49SFande Kong   Level: developer
2123c1e67a49SFande Kong 
2124f6dfbefdSBarry Smith   Note:
2125f6dfbefdSBarry Smith   The new solution is the current solution plus the update, so this norm is an indication of the size of the update
2126f6dfbefdSBarry Smith 
21271cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`
2128c1e67a49SFande Kong @*/
2129d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm)
2130d71ae5a4SJacob Faibussowitsch {
2131c1e67a49SFande Kong   PetscFunctionBegin;
2132c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21334f572ea9SToby Isaac   PetscAssertPointer(ynorm, 2);
2134c1e67a49SFande Kong   *ynorm = snes->ynorm;
21353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2136c1e67a49SFande Kong }
2137c1e67a49SFande Kong 
2138c1e67a49SFande Kong /*@
21394591eaf2SFande Kong   SNESGetSolutionNorm - Gets the last computed norm of the solution
2140c1e67a49SFande Kong 
2141c1e67a49SFande Kong   Not Collective
2142c1e67a49SFande Kong 
2143c1e67a49SFande Kong   Input Parameter:
2144f6dfbefdSBarry Smith . snes - the `SNES` context
2145c1e67a49SFande Kong 
2146c1e67a49SFande Kong   Output Parameter:
2147c1e67a49SFande Kong . xnorm - the last computed solution norm
2148c1e67a49SFande Kong 
2149c1e67a49SFande Kong   Level: developer
2150c1e67a49SFande Kong 
21511cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `SNESGetFunctionNorm()`, `SNESGetUpdateNorm()`
2152c1e67a49SFande Kong @*/
2153d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm)
2154d71ae5a4SJacob Faibussowitsch {
2155c1e67a49SFande Kong   PetscFunctionBegin;
2156c1e67a49SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
21574f572ea9SToby Isaac   PetscAssertPointer(xnorm, 2);
2158c1e67a49SFande Kong   *xnorm = snes->xnorm;
21593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2160c1e67a49SFande Kong }
2161c1e67a49SFande Kong 
2162cc4c1da9SBarry Smith /*@
2163f6dfbefdSBarry Smith   SNESSetFunctionType - Sets the `SNESFunctionType`
2164f6dfbefdSBarry Smith   of the `SNES` method.
216547073ea2SPeter Brune 
2166c3339decSBarry Smith   Logically Collective
216747073ea2SPeter Brune 
216847073ea2SPeter Brune   Input Parameters:
2169f6dfbefdSBarry Smith + snes - the `SNES` context
2170f6dfbefdSBarry Smith - type - the function type
217147073ea2SPeter Brune 
217247073ea2SPeter Brune   Level: developer
217347073ea2SPeter Brune 
2174420bcc1bSBarry Smith   Values of the function type\:
2175f6dfbefdSBarry Smith +  `SNES_FUNCTION_DEFAULT`          - the default for the given `SNESType`
2176f6dfbefdSBarry Smith .  `SNES_FUNCTION_UNPRECONDITIONED` - an unpreconditioned function evaluation (this is the function provided with `SNESSetFunction()`
2177f6dfbefdSBarry Smith -  `SNES_FUNCTION_PRECONDITIONED`   - a transformation of the function provided with `SNESSetFunction()`
2178f6dfbefdSBarry Smith 
2179420bcc1bSBarry Smith   Note:
2180f6dfbefdSBarry Smith   Different `SNESType`s use this value in different ways
2181f6dfbefdSBarry Smith 
21821cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESFunctionType`, `SNESGetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
218347073ea2SPeter Brune @*/
2184d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type)
2185d71ae5a4SJacob Faibussowitsch {
218647073ea2SPeter Brune   PetscFunctionBegin;
218747073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
218847073ea2SPeter Brune   snes->functype = type;
21893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
219047073ea2SPeter Brune }
219147073ea2SPeter Brune 
2192cc4c1da9SBarry Smith /*@
2193f6dfbefdSBarry Smith   SNESGetFunctionType - Gets the `SNESFunctionType` used in convergence and monitoring set with `SNESSetFunctionType()`
219447073ea2SPeter Brune   of the SNES method.
219547073ea2SPeter Brune 
2196c3339decSBarry Smith   Logically Collective
219747073ea2SPeter Brune 
219847073ea2SPeter Brune   Input Parameters:
2199f6dfbefdSBarry Smith + snes - the `SNES` context
2200f6dfbefdSBarry Smith - type - the type of the function evaluation, see `SNESSetFunctionType()`
220147073ea2SPeter Brune 
220247073ea2SPeter Brune   Level: advanced
220347073ea2SPeter Brune 
22041cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetFunctionType()`, `SNESFunctionType`, `SNESSetNormSchedule()`, `SNESComputeFunction()`, `VecNorm()`, `SNESSetFunction()`, `SNESSetInitialFunction()`, `SNESNormSchedule`
220547073ea2SPeter Brune @*/
2206d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type)
2207d71ae5a4SJacob Faibussowitsch {
220847073ea2SPeter Brune   PetscFunctionBegin;
220947073ea2SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
221047073ea2SPeter Brune   *type = snes->functype;
22113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2212534ebe21SPeter Brune }
2213534ebe21SPeter Brune 
2214c79ef259SPeter Brune /*@C
2215be95d8f1SBarry Smith   SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for
2216c79ef259SPeter Brune   use with composed nonlinear solvers.
2217c79ef259SPeter Brune 
2218c79ef259SPeter Brune   Input Parameters:
22199bcc50f1SBarry Smith + snes - the `SNES` context, usually of the `SNESType` `SNESNGS`
22208434afd1SBarry Smith . f    - function evaluation routine to apply Gauss-Seidel, see `SNESNGSFn` for calling sequence
222177e5a1f9SBarry Smith - ctx  - [optional] user-defined context for private data for the smoother evaluation routine (may be `NULL`)
2222c79ef259SPeter Brune 
2223dc4c0fb0SBarry Smith   Level: intermediate
2224dc4c0fb0SBarry Smith 
2225f6dfbefdSBarry Smith   Note:
2226f6dfbefdSBarry Smith   The `SNESNGS` routines are used by the composed nonlinear solver to generate
2227f6dfbefdSBarry Smith   a problem appropriate update to the solution, particularly `SNESFAS`.
2228c79ef259SPeter Brune 
22298434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGS`, `SNESGetNGS()`, `SNESNCG`, `SNESGetFunction()`, `SNESComputeNGS()`, `SNESNGSFn`
2230c79ef259SPeter Brune @*/
22318434afd1SBarry Smith PetscErrorCode SNESSetNGS(SNES snes, SNESNGSFn *f, void *ctx)
2232d71ae5a4SJacob Faibussowitsch {
22336cab3a1bSJed Brown   DM dm;
22346cab3a1bSJed Brown 
2235646217ecSPeter Brune   PetscFunctionBegin;
22366cab3a1bSJed Brown   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
22379566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22389566063dSJacob Faibussowitsch   PetscCall(DMSNESSetNGS(dm, f, ctx));
22393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2240646217ecSPeter Brune }
2241646217ecSPeter Brune 
2242bbc1464cSBarry Smith /*
2243bbc1464cSBarry Smith      This is used for -snes_mf_operator; it uses a duplicate of snes->jacobian_pre because snes->jacobian_pre cannot be
2244bbc1464cSBarry Smith    changed during the KSPSolve()
2245bbc1464cSBarry Smith */
2246d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeMFFunction(SNES snes, Vec x, Vec f, void *ctx)
2247d71ae5a4SJacob Faibussowitsch {
2248bbc1464cSBarry Smith   DM     dm;
2249bbc1464cSBarry Smith   DMSNES sdm;
2250bbc1464cSBarry Smith 
2251bbc1464cSBarry Smith   PetscFunctionBegin;
22529566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22539566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
2254bbc1464cSBarry Smith   /*  A(x)*x - b(x) */
2255bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2256792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22579566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
22580df40c35SBarry Smith     /* Cannot share nonzero pattern because of the possible use of SNESComputeJacobianDefault() */
2259ef1023bdSBarry Smith     if (!snes->picard) PetscCall(MatDuplicate(snes->jacobian_pre, MAT_DO_NOT_COPY_VALUES, &snes->picard));
2260792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22619566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->picard, x, f, f));
2262bbc1464cSBarry Smith   } else {
2263792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->picard, snes->picard, sdm->pctx));
22649566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->picard, x, f));
2265bbc1464cSBarry Smith   }
22663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2267bbc1464cSBarry Smith }
2268bbc1464cSBarry Smith 
2269d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeFunction(SNES snes, Vec x, Vec f, void *ctx)
2270d71ae5a4SJacob Faibussowitsch {
2271e03ab78fSPeter Brune   DM     dm;
2272942e3340SBarry Smith   DMSNES sdm;
22736cab3a1bSJed Brown 
22748b0a5094SBarry Smith   PetscFunctionBegin;
22759566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
22769566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
22778b0a5094SBarry Smith   /*  A(x)*x - b(x) */
2278bbc1464cSBarry Smith   if (sdm->ops->computepfunction) {
2279792fecdfSBarry Smith     PetscCallBack("SNES Picard callback function", (*sdm->ops->computepfunction)(snes, x, f, sdm->pctx));
22809566063dSJacob Faibussowitsch     PetscCall(VecScale(f, -1.0));
2281792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22829566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(snes->jacobian_pre, x, f, f));
2283bbc1464cSBarry Smith   } else {
2284792fecdfSBarry Smith     PetscCallBack("SNES Picard callback Jacobian", (*sdm->ops->computepjacobian)(snes, x, snes->jacobian, snes->jacobian_pre, sdm->pctx));
22859566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian_pre, x, f));
2286bbc1464cSBarry Smith   }
22873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22888b0a5094SBarry Smith }
22898b0a5094SBarry Smith 
2290d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESPicardComputeJacobian(SNES snes, Vec x1, Mat J, Mat B, void *ctx)
2291d71ae5a4SJacob Faibussowitsch {
22928b0a5094SBarry Smith   PetscFunctionBegin;
2293e03ab78fSPeter Brune   /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */
2294bbc1464cSBarry Smith   /* must assembly if matrix-free to get the last SNES solution */
22959566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
22969566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
22973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22988b0a5094SBarry Smith }
22998b0a5094SBarry Smith 
23008b0a5094SBarry Smith /*@C
23011d27aa22SBarry Smith   SNESSetPicard - Use `SNES` to solve the system $A(x) x = bp(x) + b $ via a Picard type iteration (Picard linearization)
23028b0a5094SBarry Smith 
2303c3339decSBarry Smith   Logically Collective
23048b0a5094SBarry Smith 
23058b0a5094SBarry Smith   Input Parameters:
2306f6dfbefdSBarry Smith + snes - the `SNES` context
2307dc4c0fb0SBarry Smith . r    - vector to store function values, may be `NULL`
23088434afd1SBarry Smith . bp   - function evaluation routine, may be `NULL`, for the calling sequence see `SNESFunctionFn`
23096b7fb656SBarry Smith . Amat - matrix with which A(x) x - bp(x) - b is to be computed
2310dc4c0fb0SBarry Smith . Pmat - matrix from which preconditioner is computed (usually the same as `Amat`)
23118434afd1SBarry Smith . J    - function to compute matrix values, for the calling sequence see `SNESJacobianFn`
2312dc4c0fb0SBarry Smith - ctx  - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`)
2313dc4c0fb0SBarry Smith 
2314dc4c0fb0SBarry Smith   Level: intermediate
23158b0a5094SBarry Smith 
23168b0a5094SBarry Smith   Notes:
23176b7fb656SBarry Smith   It is often better to provide the nonlinear function F() and some approximation to its Jacobian directly and use
2318f450aa47SBarry 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.
2319f450aa47SBarry Smith 
2320f6dfbefdSBarry Smith   One can call `SNESSetPicard()` or `SNESSetFunction()` (and possibly `SNESSetJacobian()`) but cannot call both
23218b0a5094SBarry Smith 
23221d27aa22SBarry 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}$.
23231d27aa22SBarry Smith   When an exact solver is used this corresponds to the "classic" Picard $A(x^{n}) x^{n+1} = bp(x^{n}) + b$ iteration.
23248b0a5094SBarry Smith 
2325dc4c0fb0SBarry Smith   Run with `-snes_mf_operator` to solve the system with Newton's method using A(x^{n}) to construct the preconditioner.
23268b0a5094SBarry Smith 
23270d04baf8SBarry Smith   We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then
23281d27aa22SBarry Smith   the direct Picard iteration $A(x^n) x^{n+1} = bp(x^n) + b$
23298b0a5094SBarry Smith 
23308b0a5094SBarry 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
23311d27aa22SBarry 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
23321d27aa22SBarry Smith   different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument \:-).
23338b0a5094SBarry Smith 
23341d27aa22SBarry 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
2335f6dfbefdSBarry Smith   A(x^{n}) is used to build the preconditioner
23366b7fb656SBarry Smith 
233715229ffcSPierre 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.
23386b7fb656SBarry Smith 
2339dc4c0fb0SBarry 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
23406b7fb656SBarry 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
2341f6dfbefdSBarry 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`.
2342aaa8cc7dSPierre Jolivet   See the comment in src/snes/tutorials/ex15.c.
2343bbc1464cSBarry Smith 
23449bcc50f1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetFunction()`, `SNESSetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESGetPicard()`, `SNESLineSearchPreCheckPicard()`,
23458434afd1SBarry Smith           `SNESFunctionFn`, `SNESJacobianFn`
23468b0a5094SBarry Smith @*/
23478434afd1SBarry Smith PetscErrorCode SNESSetPicard(SNES snes, Vec r, SNESFunctionFn *bp, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
2348d71ae5a4SJacob Faibussowitsch {
2349e03ab78fSPeter Brune   DM dm;
2350e03ab78fSPeter Brune 
23518b0a5094SBarry Smith   PetscFunctionBegin;
23528b0a5094SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23539566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23549566063dSJacob Faibussowitsch   PetscCall(DMSNESSetPicard(dm, bp, J, ctx));
23559566063dSJacob Faibussowitsch   PetscCall(DMSNESSetMFFunction(dm, SNESPicardComputeMFFunction, ctx));
23569566063dSJacob Faibussowitsch   PetscCall(SNESSetFunction(snes, r, SNESPicardComputeFunction, ctx));
23579566063dSJacob Faibussowitsch   PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESPicardComputeJacobian, ctx));
23583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23598b0a5094SBarry Smith }
23608b0a5094SBarry Smith 
23617971a8bfSPeter Brune /*@C
23627971a8bfSPeter Brune   SNESGetPicard - Returns the context for the Picard iteration
23637971a8bfSPeter Brune 
2364f6dfbefdSBarry Smith   Not Collective, but `Vec` is parallel if `SNES` is parallel. Collective if `Vec` is requested, but has not been created yet.
23657971a8bfSPeter Brune 
23667971a8bfSPeter Brune   Input Parameter:
2367f6dfbefdSBarry Smith . snes - the `SNES` context
23687971a8bfSPeter Brune 
2369d8d19677SJose E. Roman   Output Parameters:
2370dc4c0fb0SBarry Smith + r    - the function (or `NULL`)
23718434afd1SBarry Smith . f    - the function (or `NULL`);  for calling sequence see `SNESFunctionFn`
2372dc4c0fb0SBarry Smith . Amat - the matrix used to defined the operation A(x) x - b(x) (or `NULL`)
2373dc4c0fb0SBarry Smith . Pmat - the matrix from which the preconditioner will be constructed (or `NULL`)
23748434afd1SBarry Smith . J    - the function for matrix evaluation (or `NULL`);  for calling sequence see `SNESJacobianFn`
2375dc4c0fb0SBarry Smith - ctx  - the function context (or `NULL`)
23767971a8bfSPeter Brune 
23777971a8bfSPeter Brune   Level: advanced
23787971a8bfSPeter Brune 
23798434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetFunction()`, `SNESSetPicard()`, `SNESGetFunction()`, `SNESGetJacobian()`, `SNESGetDM()`, `SNESFunctionFn`, `SNESJacobianFn`
23807971a8bfSPeter Brune @*/
23818434afd1SBarry Smith PetscErrorCode SNESGetPicard(SNES snes, Vec *r, SNESFunctionFn **f, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
2382d71ae5a4SJacob Faibussowitsch {
23837971a8bfSPeter Brune   DM dm;
23847971a8bfSPeter Brune 
23857971a8bfSPeter Brune   PetscFunctionBegin;
23867971a8bfSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
23879566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, r, NULL, NULL));
23889566063dSJacob Faibussowitsch   PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
23899566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
23909566063dSJacob Faibussowitsch   PetscCall(DMSNESGetPicard(dm, f, J, ctx));
23913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23927971a8bfSPeter Brune }
23937971a8bfSPeter Brune 
2394d25893d9SBarry Smith /*@C
2395dc4c0fb0SBarry Smith   SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the nonlinear problem
2396d25893d9SBarry Smith 
2397c3339decSBarry Smith   Logically Collective
2398d25893d9SBarry Smith 
2399d25893d9SBarry Smith   Input Parameters:
2400f6dfbefdSBarry Smith + snes - the `SNES` context
24018434afd1SBarry Smith . func - function evaluation routine, see `SNESInitialGuessFn` for the calling sequence
2402d25893d9SBarry Smith - ctx  - [optional] user-defined context for private data for the
2403dc4c0fb0SBarry Smith          function evaluation routine (may be `NULL`)
2404d25893d9SBarry Smith 
2405d25893d9SBarry Smith   Level: intermediate
2406d25893d9SBarry Smith 
24078434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESInitialGuessFn`
2408d25893d9SBarry Smith @*/
24098434afd1SBarry Smith PetscErrorCode SNESSetComputeInitialGuess(SNES snes, SNESInitialGuessFn *func, void *ctx)
2410d71ae5a4SJacob Faibussowitsch {
2411d25893d9SBarry Smith   PetscFunctionBegin;
2412d25893d9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2413d25893d9SBarry Smith   if (func) snes->ops->computeinitialguess = func;
2414d25893d9SBarry Smith   if (ctx) snes->initialguessP = ctx;
24153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2416d25893d9SBarry Smith }
2417d25893d9SBarry Smith 
24181096aae1SMatthew Knepley /*@C
2419dc4c0fb0SBarry Smith   SNESGetRhs - Gets the vector for solving F(x) = `rhs`. If `rhs` is not set
2420dd8e379bSPierre Jolivet   it assumes a zero right-hand side.
24211096aae1SMatthew Knepley 
2422c3339decSBarry Smith   Logically Collective
24231096aae1SMatthew Knepley 
24241096aae1SMatthew Knepley   Input Parameter:
2425f6dfbefdSBarry Smith . snes - the `SNES` context
24261096aae1SMatthew Knepley 
24271096aae1SMatthew Knepley   Output Parameter:
2428dd8e379bSPierre Jolivet . rhs - the right-hand side vector or `NULL` if there is no right-hand side vector
24291096aae1SMatthew Knepley 
24301096aae1SMatthew Knepley   Level: intermediate
24311096aae1SMatthew Knepley 
24321cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`, `SNESComputeFunction()`, `SNESSetJacobian()`, `SNESSetFunction()`
24331096aae1SMatthew Knepley @*/
2434d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetRhs(SNES snes, Vec *rhs)
2435d71ae5a4SJacob Faibussowitsch {
24361096aae1SMatthew Knepley   PetscFunctionBegin;
24370700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24384f572ea9SToby Isaac   PetscAssertPointer(rhs, 2);
243985385478SLisandro Dalcin   *rhs = snes->vec_rhs;
24403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24411096aae1SMatthew Knepley }
24421096aae1SMatthew Knepley 
24439b94acceSBarry Smith /*@
2444f6dfbefdSBarry Smith   SNESComputeFunction - Calls the function that has been set with `SNESSetFunction()`.
24459b94acceSBarry Smith 
2446c3339decSBarry Smith   Collective
2447c7afd0dbSLois Curfman McInnes 
24489b94acceSBarry Smith   Input Parameters:
2449f6dfbefdSBarry Smith + snes - the `SNES` context
2450c7afd0dbSLois Curfman McInnes - x    - input vector
24519b94acceSBarry Smith 
24529b94acceSBarry Smith   Output Parameter:
2453f6dfbefdSBarry Smith . y - function vector, as set by `SNESSetFunction()`
24549b94acceSBarry Smith 
2455dc4c0fb0SBarry Smith   Level: developer
2456dc4c0fb0SBarry Smith 
245700677de2SStefano Zampini   Notes:
2458f6dfbefdSBarry Smith   `SNESComputeFunction()` is typically used within nonlinear solvers
2459bbc1464cSBarry Smith   implementations, so users would not generally call this routine themselves.
246036851e7fSLois Curfman McInnes 
246100677de2SStefano Zampini   When solving for $F(x) = b$, this routine computes $y = F(x) - b$.
246200677de2SStefano Zampini 
24631cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeMFFunction()`
24649b94acceSBarry Smith @*/
2465d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeFunction(SNES snes, Vec x, Vec y)
2466d71ae5a4SJacob Faibussowitsch {
24676cab3a1bSJed Brown   DM     dm;
2468942e3340SBarry Smith   DMSNES sdm;
24699b94acceSBarry Smith 
24703a40ed3dSBarry Smith   PetscFunctionBegin;
24710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
24720700a824SBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
24730700a824SBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2474c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2475c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2476e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2477184914b5SBarry Smith 
24789566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
24799566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
24800fdf79fbSJacob 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().");
248132f3f7c2SPeter Brune   if (sdm->ops->computefunction) {
248248a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
24839566063dSJacob Faibussowitsch     PetscCall(VecLockReadPush(x));
24848ddeebeaSSteve Benbow     /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
24858ddeebeaSSteve Benbow     snes->domainerror = PETSC_FALSE;
2486800f99ffSJeremy L Thompson     {
2487800f99ffSJeremy L Thompson       void           *ctx;
24888434afd1SBarry Smith       SNESFunctionFn *computefunction;
2489800f99ffSJeremy L Thompson       PetscCall(DMSNESGetFunction(dm, &computefunction, &ctx));
2490800f99ffSJeremy L Thompson       PetscCallBack("SNES callback function", (*computefunction)(snes, x, y, ctx));
2491800f99ffSJeremy L Thompson     }
24929566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(x));
249348a46eb9SPierre Jolivet     if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
24940fdf79fbSJacob Faibussowitsch   } else /* if (snes->vec_rhs) */ {
24959566063dSJacob Faibussowitsch     PetscCall(MatMult(snes->jacobian, x, y));
24960fdf79fbSJacob Faibussowitsch   }
24971baa6e33SBarry Smith   if (snes->vec_rhs) PetscCall(VecAXPY(y, -1.0, snes->vec_rhs));
2498ae3c334cSLois Curfman McInnes   snes->nfuncs++;
2499422a814eSBarry Smith   /*
2500422a814eSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2501422a814eSBarry Smith      propagate the value to all processes
2502422a814eSBarry Smith   */
2503f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25059b94acceSBarry Smith }
25069b94acceSBarry Smith 
2507c79ef259SPeter Brune /*@
2508*0b4b7b1cSBarry Smith   SNESComputeMFFunction - Calls the function that has been set with `DMSNESSetMFFunction()`.
2509bbc1464cSBarry Smith 
2510c3339decSBarry Smith   Collective
2511bbc1464cSBarry Smith 
2512bbc1464cSBarry Smith   Input Parameters:
2513f6dfbefdSBarry Smith + snes - the `SNES` context
2514bbc1464cSBarry Smith - x    - input vector
2515bbc1464cSBarry Smith 
2516bbc1464cSBarry Smith   Output Parameter:
2517*0b4b7b1cSBarry Smith . y - output vector
2518bbc1464cSBarry Smith 
2519dc4c0fb0SBarry Smith   Level: developer
2520dc4c0fb0SBarry Smith 
2521bbc1464cSBarry Smith   Notes:
2522420bcc1bSBarry Smith   `SNESComputeMFFunction()` is used within the matrix-vector products called by the matrix created with `MatCreateSNESMF()`
2523bbc1464cSBarry Smith   so users would not generally call this routine themselves.
2524bbc1464cSBarry Smith 
2525dd8e379bSPierre Jolivet   Since this function is intended for use with finite differencing it does not subtract the right-hand side vector provided with `SNESSolve()`
2526f6dfbefdSBarry Smith   while `SNESComputeFunction()` does. As such, this routine cannot be used with  `MatMFFDSetBase()` with a provided F function value even if it applies the
2527dd8e379bSPierre 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.
2528bbc1464cSBarry Smith 
2529*0b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFunction()`, `SNESGetFunction()`, `SNESComputeFunction()`, `MatCreateSNESMF()`, `DMSNESSetMFFunction()`
2530bbc1464cSBarry Smith @*/
2531d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeMFFunction(SNES snes, Vec x, Vec y)
2532d71ae5a4SJacob Faibussowitsch {
2533bbc1464cSBarry Smith   DM     dm;
2534bbc1464cSBarry Smith   DMSNES sdm;
2535bbc1464cSBarry Smith 
2536bbc1464cSBarry Smith   PetscFunctionBegin;
2537bbc1464cSBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2538bbc1464cSBarry Smith   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2539bbc1464cSBarry Smith   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2540bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, x, 2);
2541bbc1464cSBarry Smith   PetscCheckSameComm(snes, 1, y, 3);
2542e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2543bbc1464cSBarry Smith 
25449566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25459566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_FunctionEval, snes, x, y, 0));
25479566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(x));
2548bbc1464cSBarry Smith   /* ensure domainerror is false prior to computefunction evaluation (may not have been reset) */
2549bbc1464cSBarry Smith   snes->domainerror = PETSC_FALSE;
2550792fecdfSBarry Smith   PetscCallBack("SNES callback function", (*sdm->ops->computemffunction)(snes, x, y, sdm->mffunctionctx));
25519566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(x));
25529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_FunctionEval, snes, x, y, 0));
2553bbc1464cSBarry Smith   snes->nfuncs++;
2554bbc1464cSBarry Smith   /*
2555bbc1464cSBarry Smith      domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will
2556bbc1464cSBarry Smith      propagate the value to all processes
2557bbc1464cSBarry Smith   */
2558f480ea8aSBarry Smith   PetscCall(VecFlag(y, snes->domainerror));
25593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2560bbc1464cSBarry Smith }
2561bbc1464cSBarry Smith 
2562bbc1464cSBarry Smith /*@
2563f6dfbefdSBarry Smith   SNESComputeNGS - Calls the Gauss-Seidel function that has been set with `SNESSetNGS()`.
2564c79ef259SPeter Brune 
2565c3339decSBarry Smith   Collective
2566c79ef259SPeter Brune 
2567c79ef259SPeter Brune   Input Parameters:
2568f6dfbefdSBarry Smith + snes - the `SNES` context
2569c79ef259SPeter Brune . x    - input vector
2570c79ef259SPeter Brune - b    - rhs vector
2571c79ef259SPeter Brune 
2572c79ef259SPeter Brune   Output Parameter:
2573c79ef259SPeter Brune . x - new solution vector
2574c79ef259SPeter Brune 
2575dc4c0fb0SBarry Smith   Level: developer
2576dc4c0fb0SBarry Smith 
2577f6dfbefdSBarry Smith   Note:
2578f6dfbefdSBarry Smith   `SNESComputeNGS()` is typically used within composed nonlinear solver
2579c79ef259SPeter Brune   implementations, so most users would not generally call this routine
2580c79ef259SPeter Brune   themselves.
2581c79ef259SPeter Brune 
25828434afd1SBarry Smith .seealso: [](ch_snes), `SNESNGSFn`, `SNESSetNGS()`, `SNESComputeFunction()`, `SNESNGS`
2583c79ef259SPeter Brune @*/
2584d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeNGS(SNES snes, Vec b, Vec x)
2585d71ae5a4SJacob Faibussowitsch {
25866cab3a1bSJed Brown   DM     dm;
2587942e3340SBarry Smith   DMSNES sdm;
2588646217ecSPeter Brune 
2589646217ecSPeter Brune   PetscFunctionBegin;
2590646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
2591064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
2592064a246eSJacob Faibussowitsch   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
2593064a246eSJacob Faibussowitsch   PetscCheckSameComm(snes, 1, x, 3);
2594064a246eSJacob Faibussowitsch   if (b) PetscCheckSameComm(snes, 1, b, 2);
2595e0f629ddSJacob Faibussowitsch   if (b) PetscCall(VecValidValues_Internal(b, 2, PETSC_TRUE));
25969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_NGSEval, snes, x, b, 0));
25979566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
25989566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
25990fdf79fbSJacob Faibussowitsch   PetscCheck(sdm->ops->computegs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve().");
26009566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPush(b));
2601792fecdfSBarry Smith   PetscCallBack("SNES callback NGS", (*sdm->ops->computegs)(snes, x, b, sdm->gsctx));
26029566063dSJacob Faibussowitsch   if (b) PetscCall(VecLockReadPop(b));
26039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_NGSEval, snes, x, b, 0));
26043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2605646217ecSPeter Brune }
2606646217ecSPeter Brune 
2607494a190aSStefano Zampini static PetscErrorCode SNESComputeFunction_FD(SNES snes, Vec Xin, Vec G)
2608494a190aSStefano Zampini {
2609494a190aSStefano Zampini   Vec          X;
2610494a190aSStefano Zampini   PetscScalar *g;
2611494a190aSStefano Zampini   PetscReal    f, f2;
2612494a190aSStefano Zampini   PetscInt     low, high, N, i;
2613494a190aSStefano Zampini   PetscBool    flg;
2614494a190aSStefano Zampini   PetscReal    h = .5 * PETSC_SQRT_MACHINE_EPSILON;
2615494a190aSStefano Zampini 
2616494a190aSStefano Zampini   PetscFunctionBegin;
2617494a190aSStefano Zampini   PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_fd_delta", &h, &flg));
2618494a190aSStefano Zampini   PetscCall(VecDuplicate(Xin, &X));
2619494a190aSStefano Zampini   PetscCall(VecCopy(Xin, X));
2620494a190aSStefano Zampini   PetscCall(VecGetSize(X, &N));
2621494a190aSStefano Zampini   PetscCall(VecGetOwnershipRange(X, &low, &high));
2622494a190aSStefano Zampini   PetscCall(VecSetOption(X, VEC_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE));
2623494a190aSStefano Zampini   PetscCall(VecGetArray(G, &g));
2624494a190aSStefano Zampini   for (i = 0; i < N; i++) {
2625494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2626494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2627494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2628494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f));
2629494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, 2.0 * h, ADD_VALUES));
2630494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2631494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2632494a190aSStefano Zampini     PetscCall(SNESComputeObjective(snes, X, &f2));
2633494a190aSStefano Zampini     PetscCall(VecSetValue(X, i, -h, ADD_VALUES));
2634494a190aSStefano Zampini     PetscCall(VecAssemblyBegin(X));
2635494a190aSStefano Zampini     PetscCall(VecAssemblyEnd(X));
2636494a190aSStefano Zampini     if (i >= low && i < high) g[i - low] = (f2 - f) / (2.0 * h);
2637494a190aSStefano Zampini   }
2638494a190aSStefano Zampini   PetscCall(VecRestoreArray(G, &g));
2639494a190aSStefano Zampini   PetscCall(VecDestroy(&X));
2640494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2641494a190aSStefano Zampini }
2642494a190aSStefano Zampini 
2643494a190aSStefano Zampini PetscErrorCode SNESTestFunction(SNES snes)
2644494a190aSStefano Zampini {
2645494a190aSStefano Zampini   Vec               x, g1, g2, g3;
2646494a190aSStefano Zampini   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE;
2647494a190aSStefano Zampini   PetscReal         hcnorm, fdnorm, hcmax, fdmax, diffmax, diffnorm;
2648494a190aSStefano Zampini   PetscScalar       dot;
2649494a190aSStefano Zampini   MPI_Comm          comm;
2650494a190aSStefano Zampini   PetscViewer       viewer, mviewer;
2651494a190aSStefano Zampini   PetscViewerFormat format;
2652494a190aSStefano Zampini   PetscInt          tabs;
2653494a190aSStefano Zampini   static PetscBool  directionsprinted = PETSC_FALSE;
26548434afd1SBarry Smith   SNESObjectiveFn  *objective;
2655494a190aSStefano Zampini 
2656494a190aSStefano Zampini   PetscFunctionBegin;
2657494a190aSStefano Zampini   PetscCall(SNESGetObjective(snes, &objective, NULL));
2658494a190aSStefano Zampini   if (!objective) PetscFunctionReturn(PETSC_SUCCESS);
2659494a190aSStefano Zampini 
2660494a190aSStefano Zampini   PetscObjectOptionsBegin((PetscObject)snes);
2661494a190aSStefano Zampini   PetscCall(PetscOptionsName("-snes_test_function", "Compare hand-coded and finite difference function", "None", &test));
2662494a190aSStefano Zampini   PetscCall(PetscOptionsViewer("-snes_test_function_view", "View difference between hand-coded and finite difference function element entries", "None", &mviewer, &format, &complete_print));
2663494a190aSStefano Zampini   PetscOptionsEnd();
2664494a190aSStefano Zampini   if (!test) {
2665494a190aSStefano Zampini     if (complete_print) PetscCall(PetscViewerDestroy(&mviewer));
2666494a190aSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
2667494a190aSStefano Zampini   }
2668494a190aSStefano Zampini 
2669494a190aSStefano Zampini   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
2670494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
2671494a190aSStefano Zampini   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
2672494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
2673494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Function -------------\n"));
2674494a190aSStefano Zampini   if (!complete_print && !directionsprinted) {
2675494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_function_view and optionally -snes_test_function <threshold> to show difference\n"));
2676494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference function entries greater than <threshold>.\n"));
2677494a190aSStefano Zampini   }
2678494a190aSStefano Zampini   if (!directionsprinted) {
2679494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Function, if (for double precision runs) ||F - Ffd||/||F|| is\n"));
2680494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Function is probably correct.\n"));
2681494a190aSStefano Zampini     directionsprinted = PETSC_TRUE;
2682494a190aSStefano Zampini   }
2683494a190aSStefano Zampini   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2684494a190aSStefano Zampini 
2685494a190aSStefano Zampini   PetscCall(SNESGetSolution(snes, &x));
2686494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g1));
2687494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g2));
2688494a190aSStefano Zampini   PetscCall(VecDuplicate(x, &g3));
2689494a190aSStefano Zampini   PetscCall(SNESComputeFunction(snes, x, g1));
2690494a190aSStefano Zampini   PetscCall(SNESComputeFunction_FD(snes, x, g2));
2691494a190aSStefano Zampini 
2692494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_2, &fdnorm));
2693494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_2, &hcnorm));
2694494a190aSStefano Zampini   PetscCall(VecNorm(g2, NORM_INFINITY, &fdmax));
2695494a190aSStefano Zampini   PetscCall(VecNorm(g1, NORM_INFINITY, &hcmax));
2696494a190aSStefano Zampini   PetscCall(VecDot(g1, g2, &dot));
2697494a190aSStefano Zampini   PetscCall(VecCopy(g1, g3));
2698494a190aSStefano Zampini   PetscCall(VecAXPY(g3, -1.0, g2));
2699494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_2, &diffnorm));
2700494a190aSStefano Zampini   PetscCall(VecNorm(g3, NORM_INFINITY, &diffmax));
2701494a190aSStefano 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))));
2702494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  2-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffnorm / PetscMax(hcnorm, fdnorm)), (double)diffnorm));
2703494a190aSStefano Zampini   PetscCall(PetscViewerASCIIPrintf(viewer, "  max-norm ||F - Ffd||/||F|| = %g, ||F - Ffd|| = %g\n", (double)(diffmax / PetscMax(hcmax, fdmax)), (double)diffmax));
2704494a190aSStefano Zampini 
2705494a190aSStefano Zampini   if (complete_print) {
2706494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded function ----------\n"));
2707494a190aSStefano Zampini     PetscCall(VecView(g1, mviewer));
2708494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference function ----------\n"));
2709494a190aSStefano Zampini     PetscCall(VecView(g2, mviewer));
2710494a190aSStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference function ----------\n"));
2711494a190aSStefano Zampini     PetscCall(VecView(g3, mviewer));
2712494a190aSStefano Zampini   }
2713494a190aSStefano Zampini   PetscCall(VecDestroy(&g1));
2714494a190aSStefano Zampini   PetscCall(VecDestroy(&g2));
2715494a190aSStefano Zampini   PetscCall(VecDestroy(&g3));
2716494a190aSStefano Zampini 
2717494a190aSStefano Zampini   if (complete_print) {
2718494a190aSStefano Zampini     PetscCall(PetscViewerPopFormat(mviewer));
2719494a190aSStefano Zampini     PetscCall(PetscViewerDestroy(&mviewer));
2720494a190aSStefano Zampini   }
2721494a190aSStefano Zampini   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
2722494a190aSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2723494a190aSStefano Zampini }
2724494a190aSStefano Zampini 
2725d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestJacobian(SNES snes)
2726d71ae5a4SJacob Faibussowitsch {
272712837594SBarry Smith   Mat               A, B, C, D, jacobian;
27284df93895SStefano Zampini   Vec               x = snes->vec_sol, f;
2729e885f1abSBarry Smith   PetscReal         nrm, gnorm;
273081e7118cSBarry Smith   PetscReal         threshold = 1.e-5;
27310e276705SLisandro Dalcin   MatType           mattype;
2732e885f1abSBarry Smith   PetscInt          m, n, M, N;
2733e885f1abSBarry Smith   void             *functx;
27342cd624f9SStefano Zampini   PetscBool         complete_print = PETSC_FALSE, threshold_print = PETSC_FALSE, test = PETSC_FALSE, flg, istranspose;
27353325ff46SBarry Smith   PetscViewer       viewer, mviewer;
2736e885f1abSBarry Smith   MPI_Comm          comm;
2737e885f1abSBarry Smith   PetscInt          tabs;
273812837594SBarry Smith   static PetscBool  directionsprinted = PETSC_FALSE;
27393325ff46SBarry Smith   PetscViewerFormat format;
2740e885f1abSBarry Smith 
2741e885f1abSBarry Smith   PetscFunctionBegin;
2742d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)snes);
27439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-snes_test_jacobian", "Compare hand-coded and finite difference Jacobians", "None", &test));
27449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
27459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display", "-snes_test_jacobian_view", "3.13", NULL));
27464ead3382SBarry Smith   PetscCall(PetscOptionsViewer("-snes_test_jacobian_view", "View difference between hand-coded and finite difference Jacobians element entries", "None", &mviewer, &format, &complete_print));
27479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsDeprecated("-snes_test_jacobian_display_threshold", "-snes_test_jacobian", "3.13", "-snes_test_jacobian accepts an optional threshold (since v3.10)"));
27489566063dSJacob 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));
2749d0609cedSBarry Smith   PetscOptionsEnd();
27503ba16761SJacob Faibussowitsch   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
2751e885f1abSBarry Smith 
27529566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)snes, &comm));
27539566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
27549566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
27559566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel));
27569566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian -------------\n"));
275712837594SBarry Smith   if (!complete_print && !directionsprinted) {
27589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n"));
27599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Jacobian entries greater than <threshold>.\n"));
276012837594SBarry Smith   }
276112837594SBarry Smith   if (!directionsprinted) {
27629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
27639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Jacobian is probably correct.\n"));
276412837594SBarry Smith     directionsprinted = PETSC_TRUE;
2765e885f1abSBarry Smith   }
27661baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
2767e885f1abSBarry Smith 
27689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes->jacobian, MATMFFD, &flg));
276912837594SBarry Smith   if (!flg) jacobian = snes->jacobian;
277012837594SBarry Smith   else jacobian = snes->jacobian_pre;
277112837594SBarry Smith 
27724df93895SStefano Zampini   if (!x) PetscCall(MatCreateVecs(jacobian, &x, NULL));
27734df93895SStefano Zampini   else PetscCall(PetscObjectReference((PetscObject)x));
27749566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(x, &f));
27754df93895SStefano Zampini 
2776a82339d0SMatthew G. Knepley   /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */
27779566063dSJacob Faibussowitsch   PetscCall(SNESComputeFunction(snes, x, f));
27789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&f));
27799566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, SNESKSPTRANSPOSEONLY, &istranspose));
278012837594SBarry Smith   while (jacobian) {
27812cd624f9SStefano Zampini     Mat JT = NULL, Jsave = NULL;
27822cd624f9SStefano Zampini 
27832cd624f9SStefano Zampini     if (istranspose) {
27849566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(jacobian, &JT));
27852cd624f9SStefano Zampini       Jsave    = jacobian;
27862cd624f9SStefano Zampini       jacobian = JT;
27872cd624f9SStefano Zampini     }
27889566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)jacobian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
278912837594SBarry Smith     if (flg) {
279012837594SBarry Smith       A = jacobian;
27919566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)A));
279212837594SBarry Smith     } else {
27939566063dSJacob Faibussowitsch       PetscCall(MatComputeOperator(jacobian, MATAIJ, &A));
279412837594SBarry Smith     }
2795e885f1abSBarry Smith 
27969566063dSJacob Faibussowitsch     PetscCall(MatGetType(A, &mattype));
27979566063dSJacob Faibussowitsch     PetscCall(MatGetSize(A, &M, &N));
27989566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &m, &n));
27999566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
28009566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, mattype));
28019566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, M, N));
28029566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizesFromMats(B, A, A));
28039566063dSJacob Faibussowitsch     PetscCall(MatSetUp(B));
28049566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2805e885f1abSBarry Smith 
28069566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, NULL, NULL, &functx));
28079566063dSJacob Faibussowitsch     PetscCall(SNESComputeJacobianDefault(snes, x, B, B, functx));
280812837594SBarry Smith 
28099566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
28109566063dSJacob Faibussowitsch     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28119566063dSJacob Faibussowitsch     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
28129566063dSJacob Faibussowitsch     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
28139566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&D));
281412837594SBarry Smith     if (!gnorm) gnorm = 1; /* just in case */
28159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
281612837594SBarry Smith 
2817e885f1abSBarry Smith     if (complete_print) {
28189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Jacobian ----------\n"));
28199566063dSJacob Faibussowitsch       PetscCall(MatView(A, mviewer));
28209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Jacobian ----------\n"));
28219566063dSJacob Faibussowitsch       PetscCall(MatView(B, mviewer));
2822e885f1abSBarry Smith     }
2823e885f1abSBarry Smith 
2824df10fb39SFande Kong     if (threshold_print || complete_print) {
2825e885f1abSBarry Smith       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
2826e885f1abSBarry Smith       PetscScalar       *cvals;
2827e885f1abSBarry Smith       const PetscInt    *bcols;
2828e885f1abSBarry Smith       const PetscScalar *bvals;
2829e885f1abSBarry Smith 
28309566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
28319566063dSJacob Faibussowitsch       PetscCall(MatSetType(C, mattype));
28329566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(C, m, n, M, N));
28339566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSizesFromMats(C, A, A));
28349566063dSJacob Faibussowitsch       PetscCall(MatSetUp(C));
28359566063dSJacob Faibussowitsch       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
28360e276705SLisandro Dalcin 
28379566063dSJacob Faibussowitsch       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
28389566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
2839e885f1abSBarry Smith 
2840e885f1abSBarry Smith       for (row = Istart; row < Iend; row++) {
28419566063dSJacob Faibussowitsch         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
28429566063dSJacob Faibussowitsch         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
2843e885f1abSBarry Smith         for (j = 0, cncols = 0; j < bncols; j++) {
284423a52b1dSBarry Smith           if (PetscAbsScalar(bvals[j]) > threshold) {
2845e885f1abSBarry Smith             ccols[cncols] = bcols[j];
2846e885f1abSBarry Smith             cvals[cncols] = bvals[j];
2847e885f1abSBarry Smith             cncols += 1;
2848e885f1abSBarry Smith           }
2849e885f1abSBarry Smith         }
285048a46eb9SPierre Jolivet         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
28519566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
28529566063dSJacob Faibussowitsch         PetscCall(PetscFree2(ccols, cvals));
2853e885f1abSBarry Smith       }
28549566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
28559566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
28569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n", (double)threshold));
28579566063dSJacob Faibussowitsch       PetscCall(MatView(C, complete_print ? mviewer : viewer));
28589566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&C));
2859e885f1abSBarry Smith     }
28609566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&A));
28619566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
28629566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&JT));
28632cd624f9SStefano Zampini     if (Jsave) jacobian = Jsave;
286412837594SBarry Smith     if (jacobian != snes->jacobian_pre) {
286512837594SBarry Smith       jacobian = snes->jacobian_pre;
28669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Jacobian for preconditioner -------------\n"));
28679371c9d4SSatish Balay     } else jacobian = NULL;
286812837594SBarry Smith   }
28699566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
28701baa6e33SBarry Smith   if (complete_print) PetscCall(PetscViewerPopFormat(mviewer));
2871648c30bcSBarry Smith   if (mviewer) PetscCall(PetscViewerDestroy(&mviewer));
28729566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
28733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2874e885f1abSBarry Smith }
2875e885f1abSBarry Smith 
287662fef451SLois Curfman McInnes /*@
2877f6dfbefdSBarry Smith   SNESComputeJacobian - Computes the Jacobian matrix that has been set with `SNESSetJacobian()`.
287862fef451SLois Curfman McInnes 
2879c3339decSBarry Smith   Collective
2880c7afd0dbSLois Curfman McInnes 
288162fef451SLois Curfman McInnes   Input Parameters:
2882f6dfbefdSBarry Smith + snes - the `SNES` context
2883e4094ef1SJacob Faibussowitsch - X    - input vector
288462fef451SLois Curfman McInnes 
288562fef451SLois Curfman McInnes   Output Parameters:
2886c7afd0dbSLois Curfman McInnes + A - Jacobian matrix
2887420bcc1bSBarry Smith - B - optional matrix for building the preconditioner, usually the same as `A`
2888fee21e36SBarry Smith 
2889e35cf81dSBarry Smith   Options Database Keys:
289067b8a455SSatish Balay + -snes_lag_preconditioner <lag>           - how often to rebuild preconditioner
289167b8a455SSatish Balay . -snes_lag_jacobian <lag>                 - how often to rebuild Jacobian
2892455a5933SJed 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.
2893455a5933SJed 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
2894693365a8SJed Brown . -snes_compare_explicit                   - Compare the computed Jacobian to the finite difference Jacobian and output the differences
2895693365a8SJed Brown . -snes_compare_explicit_draw              - Compare the computed Jacobian to the finite difference Jacobian and draw the result
2896693365a8SJed Brown . -snes_compare_explicit_contour           - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result
28974c30e9fbSJed Brown . -snes_compare_operator                   - Make the comparison options above use the operator instead of the preconditioning matrix
289894d6a431SBarry Smith . -snes_compare_coloring                   - Compute the finite difference Jacobian using coloring and display norms of difference
2899a5b23f4aSJose E. Roman . -snes_compare_coloring_display           - Compute the finite difference Jacobian using coloring and display verbose differences
2900c01495d3SJed Brown . -snes_compare_coloring_threshold         - Display only those matrix entries that differ by more than a given threshold
2901dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_atol    - Absolute tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2902dc4c0fb0SBarry Smith . -snes_compare_coloring_threshold_rtol    - Relative tolerance for difference in matrix entries to be displayed by `-snes_compare_coloring_threshold`
2903a5b23f4aSJose E. Roman . -snes_compare_coloring_draw              - Compute the finite difference Jacobian using coloring and draw differences
2904a5b23f4aSJose E. Roman - -snes_compare_coloring_draw_contour      - Compute the finite difference Jacobian using coloring and show contours of matrices and differences
2905c01495d3SJed Brown 
2906dc4c0fb0SBarry Smith   Level: developer
2907dc4c0fb0SBarry Smith 
2908f6dfbefdSBarry Smith   Note:
290962fef451SLois Curfman McInnes   Most users should not need to explicitly call this routine, as it
291062fef451SLois Curfman McInnes   is used internally within the nonlinear solvers.
291162fef451SLois Curfman McInnes 
2912420bcc1bSBarry Smith   Developer Note:
2913dc4c0fb0SBarry 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
2914420bcc1bSBarry Smith   with the `SNESType` of test that has been removed.
2915e885f1abSBarry Smith 
29161cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetJacobian()`, `KSPSetOperators()`, `MatStructure`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobian()`
291762fef451SLois Curfman McInnes @*/
2918d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESComputeJacobian(SNES snes, Vec X, Mat A, Mat B)
2919d71ae5a4SJacob Faibussowitsch {
2920ace3abfcSBarry Smith   PetscBool flag;
29216cab3a1bSJed Brown   DM        dm;
2922942e3340SBarry Smith   DMSNES    sdm;
2923e0e3a89bSBarry Smith   KSP       ksp;
29243a40ed3dSBarry Smith 
29253a40ed3dSBarry Smith   PetscFunctionBegin;
29260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
29270700a824SBarry Smith   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2928c9780b6fSBarry Smith   PetscCheckSameComm(snes, 1, X, 2);
2929e0f629ddSJacob Faibussowitsch   PetscCall(VecValidValues_Internal(X, 2, PETSC_TRUE));
29309566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
29319566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
29323232da50SPeter Brune 
293301c1178eSBarry Smith   /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix-free */
2934fe3ffe1eSBarry Smith   if (snes->lagjacobian == -2) {
2935fe3ffe1eSBarry Smith     snes->lagjacobian = -1;
2936f5af7f23SKarl Rupp 
29379566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n"));
2938fe3ffe1eSBarry Smith   } else if (snes->lagjacobian == -1) {
29399566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is -1\n"));
29409566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2941ebd3b9afSBarry Smith     if (flag) {
29429566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29439566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2944ebd3b9afSBarry Smith     }
29453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
294637ec4e1aSPeter Brune   } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) {
294763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing Jacobian/preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagjacobian, snes->iter));
29489566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMFFD, &flag));
2949ebd3b9afSBarry Smith     if (flag) {
29509566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29519566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2952ebd3b9afSBarry Smith     }
29533ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2954e35cf81dSBarry Smith   }
2955efd4aadfSBarry Smith   if (snes->npc && snes->npcside == PC_LEFT) {
29569566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29579566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
29583ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2959d728fb7dSPeter Brune   }
2960e35cf81dSBarry Smith 
29619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(SNES_JacobianEval, snes, X, A, B));
29629566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(X));
2963800f99ffSJeremy L Thompson   {
2964800f99ffSJeremy L Thompson     void           *ctx;
29658434afd1SBarry Smith     SNESJacobianFn *J;
2966800f99ffSJeremy L Thompson     PetscCall(DMSNESGetJacobian(dm, &J, &ctx));
2967800f99ffSJeremy L Thompson     PetscCallBack("SNES callback Jacobian", (*J)(snes, X, A, B, ctx));
2968800f99ffSJeremy L Thompson   }
29699566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(X));
29709566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(SNES_JacobianEval, snes, X, A, B));
297128d58a37SPierre Jolivet 
297228d58a37SPierre Jolivet   /* attach latest linearization point to the preconditioning matrix */
29739566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)B, "__SNES_latest_X", (PetscObject)X));
2974a8054027SBarry Smith 
2975e0e3a89bSBarry Smith   /* the next line ensures that snes->ksp exists */
29769566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
29773b4f5425SBarry Smith   if (snes->lagpreconditioner == -2) {
29789566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner exactly once since lag is -2\n"));
29799566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
29803b4f5425SBarry Smith     snes->lagpreconditioner = -1;
29813b4f5425SBarry Smith   } else if (snes->lagpreconditioner == -1) {
29829566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is -1\n"));
29839566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
298437ec4e1aSPeter Brune   } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) {
298563a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Reusing preconditioner because lag is %" PetscInt_FMT " and SNES iteration is %" PetscInt_FMT "\n", snes->lagpreconditioner, snes->iter));
29869566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_TRUE));
2987d1e9a80fSBarry Smith   } else {
29889566063dSJacob Faibussowitsch     PetscCall(PetscInfo(snes, "Rebuilding preconditioner\n"));
29899566063dSJacob Faibussowitsch     PetscCall(KSPSetReusePreconditioner(snes->ksp, PETSC_FALSE));
2990a8054027SBarry Smith   }
2991a8054027SBarry Smith 
29924df93895SStefano Zampini   /* monkey business to allow testing Jacobians in multilevel solvers.
29934df93895SStefano Zampini      This is needed because the SNESTestXXX interface does not accept vectors and matrices */
29944df93895SStefano Zampini   {
29954df93895SStefano Zampini     Vec xsave            = snes->vec_sol;
29964df93895SStefano Zampini     Mat jacobiansave     = snes->jacobian;
29974df93895SStefano Zampini     Mat jacobian_presave = snes->jacobian_pre;
29984df93895SStefano Zampini 
29994df93895SStefano Zampini     snes->vec_sol      = X;
30004df93895SStefano Zampini     snes->jacobian     = A;
30014df93895SStefano Zampini     snes->jacobian_pre = B;
3002494a190aSStefano Zampini     PetscCall(SNESTestFunction(snes));
30039566063dSJacob Faibussowitsch     PetscCall(SNESTestJacobian(snes));
3004494a190aSStefano Zampini 
30054df93895SStefano Zampini     snes->vec_sol      = xsave;
30064df93895SStefano Zampini     snes->jacobian     = jacobiansave;
30074df93895SStefano Zampini     snes->jacobian_pre = jacobian_presave;
30084df93895SStefano Zampini   }
30094df93895SStefano Zampini 
3010693365a8SJed Brown   {
3011693365a8SJed Brown     PetscBool flag = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_operator = PETSC_FALSE;
3012648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit", NULL, NULL, &flag));
3013648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw", NULL, NULL, &flag_draw));
3014648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_explicit_draw_contour", NULL, NULL, &flag_contour));
3015648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_operator", NULL, NULL, &flag_operator));
3016693365a8SJed Brown     if (flag || flag_draw || flag_contour) {
30170298fd71SBarry Smith       Mat         Bexp_mine = NULL, Bexp, FDexp;
3018693365a8SJed Brown       PetscViewer vdraw, vstdout;
30196b3a5b13SJed Brown       PetscBool   flg;
3020693365a8SJed Brown       if (flag_operator) {
30219566063dSJacob Faibussowitsch         PetscCall(MatComputeOperator(A, MATAIJ, &Bexp_mine));
3022693365a8SJed Brown         Bexp = Bexp_mine;
3023693365a8SJed Brown       } else {
3024693365a8SJed Brown         /* See if the preconditioning matrix can be viewed and added directly */
30259566063dSJacob Faibussowitsch         PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)B, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
302694ab13aaSBarry Smith         if (flg) Bexp = B;
3027693365a8SJed Brown         else {
3028693365a8SJed Brown           /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */
30299566063dSJacob Faibussowitsch           PetscCall(MatComputeOperator(B, MATAIJ, &Bexp_mine));
3030693365a8SJed Brown           Bexp = Bexp_mine;
3031693365a8SJed Brown         }
3032693365a8SJed Brown       }
30339566063dSJacob Faibussowitsch       PetscCall(MatConvert(Bexp, MATSAME, MAT_INITIAL_MATRIX, &FDexp));
30349566063dSJacob Faibussowitsch       PetscCall(SNESComputeJacobianDefault(snes, X, FDexp, FDexp, NULL));
30359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
3036693365a8SJed Brown       if (flag_draw || flag_contour) {
30379566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Explicit Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
30389566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30390298fd71SBarry Smith       } else vdraw = NULL;
30409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit %s\n", flag_operator ? "Jacobian" : "preconditioning Jacobian"));
30419566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(Bexp, vstdout));
30429566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bexp, vdraw));
30439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Finite difference Jacobian\n"));
30449566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
30459566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(FDexp, vdraw));
30469566063dSJacob Faibussowitsch       PetscCall(MatAYPX(FDexp, -1.0, Bexp, SAME_NONZERO_PATTERN));
30479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian\n"));
30489566063dSJacob Faibussowitsch       if (flag) PetscCall(MatView(FDexp, vstdout));
3049693365a8SJed Brown       if (vdraw) { /* Always use contour for the difference */
30509566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
30519566063dSJacob Faibussowitsch         PetscCall(MatView(FDexp, vdraw));
30529566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
3053693365a8SJed Brown       }
30549566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
30559566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
30569566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bexp_mine));
30579566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&FDexp));
3058693365a8SJed Brown     }
3059693365a8SJed Brown   }
30604c30e9fbSJed Brown   {
30616719d8e4SJed Brown     PetscBool flag = PETSC_FALSE, flag_display = PETSC_FALSE, flag_draw = PETSC_FALSE, flag_contour = PETSC_FALSE, flag_threshold = PETSC_FALSE;
30626719d8e4SJed Brown     PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON, threshold_rtol = 10 * PETSC_SQRT_MACHINE_EPSILON;
3063648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring", NULL, NULL, &flag));
3064648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_display", NULL, NULL, &flag_display));
3065648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw", NULL, NULL, &flag_draw));
3066648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_draw_contour", NULL, NULL, &flag_contour));
3067648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold", NULL, NULL, &flag_threshold));
306827b0f280SBarry Smith     if (flag_threshold) {
30699566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_rtol", &threshold_rtol, NULL));
30709566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_compare_coloring_threshold_atol", &threshold_atol, NULL));
307127b0f280SBarry Smith     }
30726719d8e4SJed Brown     if (flag || flag_display || flag_draw || flag_contour || flag_threshold) {
30734c30e9fbSJed Brown       Mat             Bfd;
30744c30e9fbSJed Brown       PetscViewer     vdraw, vstdout;
3075335efc43SPeter Brune       MatColoring     coloring;
30764c30e9fbSJed Brown       ISColoring      iscoloring;
30774c30e9fbSJed Brown       MatFDColoring   matfdcoloring;
30788434afd1SBarry Smith       SNESFunctionFn *func;
30794c30e9fbSJed Brown       void           *funcctx;
30806719d8e4SJed Brown       PetscReal       norm1, norm2, normmax;
30814c30e9fbSJed Brown 
30829566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &Bfd));
30839566063dSJacob Faibussowitsch       PetscCall(MatColoringCreate(Bfd, &coloring));
30849566063dSJacob Faibussowitsch       PetscCall(MatColoringSetType(coloring, MATCOLORINGSL));
30859566063dSJacob Faibussowitsch       PetscCall(MatColoringSetFromOptions(coloring));
30869566063dSJacob Faibussowitsch       PetscCall(MatColoringApply(coloring, &iscoloring));
30879566063dSJacob Faibussowitsch       PetscCall(MatColoringDestroy(&coloring));
30889566063dSJacob Faibussowitsch       PetscCall(MatFDColoringCreate(Bfd, iscoloring, &matfdcoloring));
30899566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30909566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetUp(Bfd, iscoloring, matfdcoloring));
30919566063dSJacob Faibussowitsch       PetscCall(ISColoringDestroy(&iscoloring));
30924c30e9fbSJed Brown 
30934c30e9fbSJed Brown       /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */
30949566063dSJacob Faibussowitsch       PetscCall(SNESGetFunction(snes, NULL, &func, &funcctx));
30959566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))func, funcctx));
30969566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring, ((PetscObject)snes)->prefix));
30979566063dSJacob Faibussowitsch       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring, "coloring_"));
30989566063dSJacob Faibussowitsch       PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
30999566063dSJacob Faibussowitsch       PetscCall(MatFDColoringApply(Bfd, matfdcoloring, X, snes));
31009566063dSJacob Faibussowitsch       PetscCall(MatFDColoringDestroy(&matfdcoloring));
31014c30e9fbSJed Brown 
31029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes), &vstdout));
31034c30e9fbSJed Brown       if (flag_draw || flag_contour) {
31049566063dSJacob Faibussowitsch         PetscCall(PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes), NULL, "Colored Jacobians", PETSC_DECIDE, PETSC_DECIDE, 300, 300, &vdraw));
31059566063dSJacob Faibussowitsch         if (flag_contour) PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31060298fd71SBarry Smith       } else vdraw = NULL;
31079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Explicit preconditioning Jacobian\n"));
31089566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(B, vstdout));
31099566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(B, vdraw));
31109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "Colored Finite difference Jacobian\n"));
31119566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31129566063dSJacob Faibussowitsch       if (vdraw) PetscCall(MatView(Bfd, vdraw));
31139566063dSJacob Faibussowitsch       PetscCall(MatAYPX(Bfd, -1.0, B, SAME_NONZERO_PATTERN));
31149566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_1, &norm1));
31159566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_FROBENIUS, &norm2));
31169566063dSJacob Faibussowitsch       PetscCall(MatNorm(Bfd, NORM_MAX, &normmax));
31179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(vstdout, "User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n", (double)norm1, (double)norm2, (double)normmax));
31189566063dSJacob Faibussowitsch       if (flag_display) PetscCall(MatView(Bfd, vstdout));
31194c30e9fbSJed Brown       if (vdraw) { /* Always use contour for the difference */
31209566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(vdraw, PETSC_VIEWER_DRAW_CONTOUR));
31219566063dSJacob Faibussowitsch         PetscCall(MatView(Bfd, vdraw));
31229566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(vdraw));
31234c30e9fbSJed Brown       }
31249566063dSJacob Faibussowitsch       if (flag_contour) PetscCall(PetscViewerPopFormat(vdraw));
31256719d8e4SJed Brown 
31266719d8e4SJed Brown       if (flag_threshold) {
31276719d8e4SJed Brown         PetscInt bs, rstart, rend, i;
31289566063dSJacob Faibussowitsch         PetscCall(MatGetBlockSize(B, &bs));
31299566063dSJacob Faibussowitsch         PetscCall(MatGetOwnershipRange(B, &rstart, &rend));
31306719d8e4SJed Brown         for (i = rstart; i < rend; i++) {
31316719d8e4SJed Brown           const PetscScalar *ba, *ca;
31326719d8e4SJed Brown           const PetscInt    *bj, *cj;
31336719d8e4SJed Brown           PetscInt           bn, cn, j, maxentrycol = -1, maxdiffcol = -1, maxrdiffcol = -1;
31346719d8e4SJed Brown           PetscReal          maxentry = 0, maxdiff = 0, maxrdiff = 0;
31359566063dSJacob Faibussowitsch           PetscCall(MatGetRow(B, i, &bn, &bj, &ba));
31369566063dSJacob Faibussowitsch           PetscCall(MatGetRow(Bfd, i, &cn, &cj, &ca));
31375f80ce2aSJacob Faibussowitsch           PetscCheck(bn == cn, ((PetscObject)A)->comm, PETSC_ERR_PLIB, "Unexpected different nonzero pattern in -snes_compare_coloring_threshold");
31386719d8e4SJed Brown           for (j = 0; j < bn; j++) {
31396719d8e4SJed Brown             PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
31406719d8e4SJed Brown             if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) {
31416719d8e4SJed Brown               maxentrycol = bj[j];
31426719d8e4SJed Brown               maxentry    = PetscRealPart(ba[j]);
31436719d8e4SJed Brown             }
31446719d8e4SJed Brown             if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) {
31456719d8e4SJed Brown               maxdiffcol = bj[j];
31466719d8e4SJed Brown               maxdiff    = PetscRealPart(ca[j]);
31476719d8e4SJed Brown             }
31486719d8e4SJed Brown             if (rdiff > maxrdiff) {
31496719d8e4SJed Brown               maxrdiffcol = bj[j];
31506719d8e4SJed Brown               maxrdiff    = rdiff;
31516719d8e4SJed Brown             }
31526719d8e4SJed Brown           }
31536719d8e4SJed Brown           if (maxrdiff > 1) {
315463a3b9bcSJacob 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));
31556719d8e4SJed Brown             for (j = 0; j < bn; j++) {
31566719d8e4SJed Brown               PetscReal rdiff;
31576719d8e4SJed Brown               rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol * PetscAbsScalar(ba[j]));
315848a46eb9SPierre Jolivet               if (rdiff > 1) PetscCall(PetscViewerASCIIPrintf(vstdout, " (%" PetscInt_FMT ",%g:%g)", bj[j], (double)PetscRealPart(ba[j]), (double)PetscRealPart(ca[j])));
31596719d8e4SJed Brown             }
316063a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(vstdout, "\n"));
31616719d8e4SJed Brown           }
31629566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(B, i, &bn, &bj, &ba));
31639566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(Bfd, i, &cn, &cj, &ca));
31646719d8e4SJed Brown         }
31656719d8e4SJed Brown       }
31669566063dSJacob Faibussowitsch       PetscCall(PetscViewerDestroy(&vdraw));
31679566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&Bfd));
31684c30e9fbSJed Brown     }
31694c30e9fbSJed Brown   }
31703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31719b94acceSBarry Smith }
31729b94acceSBarry Smith 
31739b94acceSBarry Smith /*@C
31749b94acceSBarry Smith   SNESSetJacobian - Sets the function to compute Jacobian as well as the
3175044dda88SLois Curfman McInnes   location to store the matrix.
31769b94acceSBarry Smith 
3177c3339decSBarry Smith   Logically Collective
3178c7afd0dbSLois Curfman McInnes 
31799b94acceSBarry Smith   Input Parameters:
3180f6dfbefdSBarry Smith + snes - the `SNES` context
3181e5d3d808SBarry Smith . Amat - the matrix that defines the (approximate) Jacobian
3182dc4c0fb0SBarry Smith . Pmat - the matrix to be used in constructing the preconditioner, usually the same as `Amat`.
31838434afd1SBarry Smith . J    - Jacobian evaluation routine (if `NULL` then `SNES` retains any previously set value), see `SNESJacobianFn` for details
3184c7afd0dbSLois Curfman McInnes - ctx  - [optional] user-defined context for private data for the
3185dc4c0fb0SBarry Smith          Jacobian evaluation routine (may be `NULL`) (if `NULL` then `SNES` retains any previously set value)
3186dc4c0fb0SBarry Smith 
3187dc4c0fb0SBarry Smith   Level: beginner
31889b94acceSBarry Smith 
31899b94acceSBarry Smith   Notes:
3190dc4c0fb0SBarry Smith   If the `Amat` matrix and `Pmat` matrix are different you must call `MatAssemblyBegin()`/`MatAssemblyEnd()` on
319116913363SBarry Smith   each matrix.
319216913363SBarry Smith 
3193dc4c0fb0SBarry Smith   If you know the operator `Amat` has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null
3194dc4c0fb0SBarry Smith   space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process.
3195895c21f2SBarry Smith 
3196dc4c0fb0SBarry Smith   If using `SNESComputeJacobianDefaultColor()` to assemble a Jacobian, the `ctx` argument
3197f6dfbefdSBarry Smith   must be a `MatFDColoring`.
3198a8a26c1eSJed Brown 
3199c3cc8fd1SJed Brown   Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian.  One common
3200f6dfbefdSBarry Smith   example is to use the "Picard linearization" which only differentiates through the highest order parts of each term using `SNESSetPicard()`
3201c3cc8fd1SJed Brown 
32021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSPSetOperators()`, `SNESSetFunction()`, `MatMFFDComputeJacobian()`, `SNESComputeJacobianDefaultColor()`, `MatStructure`,
32038434afd1SBarry Smith           `SNESSetPicard()`, `SNESJacobianFn`, `SNESFunctionFn`
32049b94acceSBarry Smith @*/
32058434afd1SBarry Smith PetscErrorCode SNESSetJacobian(SNES snes, Mat Amat, Mat Pmat, SNESJacobianFn *J, void *ctx)
3206d71ae5a4SJacob Faibussowitsch {
32076cab3a1bSJed Brown   DM dm;
32083a7fca6bSBarry Smith 
32093a40ed3dSBarry Smith   PetscFunctionBegin;
32100700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3211e5d3d808SBarry Smith   if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2);
3212e5d3d808SBarry Smith   if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3);
3213e5d3d808SBarry Smith   if (Amat) PetscCheckSameComm(snes, 1, Amat, 2);
3214e5d3d808SBarry Smith   if (Pmat) PetscCheckSameComm(snes, 1, Pmat, 3);
32159566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32169566063dSJacob Faibussowitsch   PetscCall(DMSNESSetJacobian(dm, J, ctx));
3217e5d3d808SBarry Smith   if (Amat) {
32189566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Amat));
32199566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian));
3220f5af7f23SKarl Rupp 
3221e5d3d808SBarry Smith     snes->jacobian = Amat;
32223a7fca6bSBarry Smith   }
3223e5d3d808SBarry Smith   if (Pmat) {
32249566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)Pmat));
32259566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&snes->jacobian_pre));
3226f5af7f23SKarl Rupp 
3227e5d3d808SBarry Smith     snes->jacobian_pre = Pmat;
32283a7fca6bSBarry Smith   }
32293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32309b94acceSBarry Smith }
323162fef451SLois Curfman McInnes 
3232c2aafc4cSSatish Balay /*@C
3233b4fd4287SBarry Smith   SNESGetJacobian - Returns the Jacobian matrix and optionally the user
3234b4fd4287SBarry Smith   provided context for evaluating the Jacobian.
3235b4fd4287SBarry Smith 
3236420bcc1bSBarry Smith   Not Collective, but `Mat` object will be parallel if `SNES` is
3237c7afd0dbSLois Curfman McInnes 
3238b4fd4287SBarry Smith   Input Parameter:
3239b4fd4287SBarry Smith . snes - the nonlinear solver context
3240b4fd4287SBarry Smith 
3241b4fd4287SBarry Smith   Output Parameters:
3242dc4c0fb0SBarry Smith + Amat - location to stash (approximate) Jacobian matrix (or `NULL`)
3243dc4c0fb0SBarry Smith . Pmat - location to stash matrix used to compute the preconditioner (or `NULL`)
32448434afd1SBarry Smith . J    - location to put Jacobian function (or `NULL`), for calling sequence see `SNESJacobianFn`
3245dc4c0fb0SBarry Smith - ctx  - location to stash Jacobian ctx (or `NULL`)
3246fee21e36SBarry Smith 
324736851e7fSLois Curfman McInnes   Level: advanced
324836851e7fSLois Curfman McInnes 
32498434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `Mat`, `SNESSetJacobian()`, `SNESComputeJacobian()`, `SNESJacobianFn`, `SNESGetFunction()`
3250b4fd4287SBarry Smith @*/
32518434afd1SBarry Smith PetscErrorCode SNESGetJacobian(SNES snes, Mat *Amat, Mat *Pmat, SNESJacobianFn **J, void **ctx)
3252d71ae5a4SJacob Faibussowitsch {
32536cab3a1bSJed Brown   DM dm;
32546cab3a1bSJed Brown 
32553a40ed3dSBarry Smith   PetscFunctionBegin;
32560700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3257e5d3d808SBarry Smith   if (Amat) *Amat = snes->jacobian;
3258e5d3d808SBarry Smith   if (Pmat) *Pmat = snes->jacobian_pre;
32599566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
3260800f99ffSJeremy L Thompson   PetscCall(DMSNESGetJacobian(dm, J, ctx));
32613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3262b4fd4287SBarry Smith }
3263b4fd4287SBarry Smith 
3264d71ae5a4SJacob Faibussowitsch static PetscErrorCode SNESSetDefaultComputeJacobian(SNES snes)
3265d71ae5a4SJacob Faibussowitsch {
326658b371f3SBarry Smith   DM     dm;
326758b371f3SBarry Smith   DMSNES sdm;
326858b371f3SBarry Smith 
326958b371f3SBarry Smith   PetscFunctionBegin;
32709566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
32719566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
327258b371f3SBarry Smith   if (!sdm->ops->computejacobian && snes->jacobian_pre) {
327358b371f3SBarry Smith     DM        dm;
327458b371f3SBarry Smith     PetscBool isdense, ismf;
327558b371f3SBarry Smith 
32769566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
32779566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &isdense, MATSEQDENSE, MATMPIDENSE, MATDENSE, NULL));
32789566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)snes->jacobian_pre, &ismf, MATMFFD, MATSHELL, NULL));
327958b371f3SBarry Smith     if (isdense) {
32809566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefault, NULL));
328158b371f3SBarry Smith     } else if (!ismf) {
32829566063dSJacob Faibussowitsch       PetscCall(DMSNESSetJacobian(dm, SNESComputeJacobianDefaultColor, NULL));
328358b371f3SBarry Smith     }
328458b371f3SBarry Smith   }
32853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
328658b371f3SBarry Smith }
328758b371f3SBarry Smith 
32889b94acceSBarry Smith /*@
32899b94acceSBarry Smith   SNESSetUp - Sets up the internal data structures for the later use
3290*0b4b7b1cSBarry Smith   of a nonlinear solver `SNESSolve()`.
32919b94acceSBarry Smith 
3292c3339decSBarry Smith   Collective
3293fee21e36SBarry Smith 
32942fe279fdSBarry Smith   Input Parameter:
3295f6dfbefdSBarry Smith . snes - the `SNES` context
3296c7afd0dbSLois Curfman McInnes 
3297dc4c0fb0SBarry Smith   Level: advanced
3298dc4c0fb0SBarry Smith 
3299f6dfbefdSBarry Smith   Note:
3300*0b4b7b1cSBarry Smith   For basic use of the `SNES` solvers the user does not need to explicitly call
3301f6dfbefdSBarry Smith   `SNESSetUp()`, since these actions will automatically occur during
3302f6dfbefdSBarry Smith   the call to `SNESSolve()`.  However, if one wishes to control this
3303f6dfbefdSBarry Smith   phase separately, `SNESSetUp()` should be called after `SNESCreate()`
3304f6dfbefdSBarry Smith   and optional routines of the form SNESSetXXX(), but before `SNESSolve()`.
3305272ac6f2SLois Curfman McInnes 
3306*0b4b7b1cSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`, `SNESDestroy()`, `SNESSetFromOptions()`
33079b94acceSBarry Smith @*/
3308d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetUp(SNES snes)
3309d71ae5a4SJacob Faibussowitsch {
33106cab3a1bSJed Brown   DM             dm;
3311942e3340SBarry Smith   DMSNES         sdm;
3312c35f09e5SBarry Smith   SNESLineSearch linesearch, pclinesearch;
33136e2a1849SPeter Brune   void          *lsprectx, *lspostctx;
33149b5c1c08SStefano Zampini   PetscBool      mf_operator, mf;
33159b5c1c08SStefano Zampini   Vec            f, fpc;
33169b5c1c08SStefano Zampini   void          *funcctx;
33179b5c1c08SStefano Zampini   void          *jacctx, *appctx;
33189b5c1c08SStefano Zampini   Mat            j, jpre;
33196b2b7091SBarry Smith   PetscErrorCode (*precheck)(SNESLineSearch, Vec, Vec, PetscBool *, void *);
33206b2b7091SBarry Smith   PetscErrorCode (*postcheck)(SNESLineSearch, Vec, Vec, Vec, PetscBool *, PetscBool *, void *);
33218434afd1SBarry Smith   SNESFunctionFn *func;
33228434afd1SBarry Smith   SNESJacobianFn *jac;
33233a40ed3dSBarry Smith 
33243a40ed3dSBarry Smith   PetscFunctionBegin;
33250700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
33263ba16761SJacob Faibussowitsch   if (snes->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
3327fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventBegin(SNES_SetUp, snes, 0, 0, 0));
33289b94acceSBarry Smith 
332948a46eb9SPierre Jolivet   if (!((PetscObject)snes)->type_name) PetscCall(SNESSetType(snes, SNESNEWTONLS));
333085385478SLisandro Dalcin 
33319566063dSJacob Faibussowitsch   PetscCall(SNESGetFunction(snes, &snes->vec_func, NULL, NULL));
333258c9b817SLisandro Dalcin 
33339566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
33349566063dSJacob Faibussowitsch   PetscCall(DMGetDMSNES(dm, &sdm));
33359566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
333658b371f3SBarry Smith 
333748a46eb9SPierre Jolivet   if (!snes->vec_func) PetscCall(DMCreateGlobalVector(dm, &snes->vec_func));
3338efd51863SBarry Smith 
333948a46eb9SPierre Jolivet   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
3340b710008aSBarry Smith 
3341d8d34be6SBarry Smith   if (snes->linesearch) {
33429566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
33439566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetFunction(snes->linesearch, SNESComputeFunction));
3344d8d34be6SBarry Smith   }
33459e764e56SPeter Brune 
33469b5c1c08SStefano Zampini   PetscCall(SNESGetUseMatrixFree(snes, &mf_operator, &mf));
3347b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
3348172a4300SPeter Brune     snes->mf          = PETSC_TRUE;
3349172a4300SPeter Brune     snes->mf_operator = PETSC_FALSE;
3350172a4300SPeter Brune   }
3351d8f46077SPeter Brune 
3352efd4aadfSBarry Smith   if (snes->npc) {
33536e2a1849SPeter Brune     /* copy the DM over */
33549566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
33559566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, dm));
33566e2a1849SPeter Brune 
33579566063dSJacob Faibussowitsch     PetscCall(SNESGetFunction(snes, &f, &func, &funcctx));
33589566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(f, &fpc));
33599566063dSJacob Faibussowitsch     PetscCall(SNESSetFunction(snes->npc, fpc, func, funcctx));
33609566063dSJacob Faibussowitsch     PetscCall(SNESGetJacobian(snes, &j, &jpre, &jac, &jacctx));
33619566063dSJacob Faibussowitsch     PetscCall(SNESSetJacobian(snes->npc, j, jpre, jac, jacctx));
33629566063dSJacob Faibussowitsch     PetscCall(SNESGetApplicationContext(snes, &appctx));
33639566063dSJacob Faibussowitsch     PetscCall(SNESSetApplicationContext(snes->npc, appctx));
33649b5c1c08SStefano Zampini     PetscCall(SNESSetUseMatrixFree(snes->npc, mf_operator, mf));
33659566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&fpc));
33666e2a1849SPeter Brune 
33676e2a1849SPeter Brune     /* copy the function pointers over */
33689566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)snes, (PetscObject)snes->npc));
33696e2a1849SPeter Brune 
33706e2a1849SPeter Brune     /* default to 1 iteration */
33719566063dSJacob Faibussowitsch     PetscCall(SNESSetTolerances(snes->npc, 0.0, 0.0, 0.0, 1, snes->npc->max_funcs));
3372efd4aadfSBarry Smith     if (snes->npcside == PC_RIGHT) {
33739566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_FINAL_ONLY));
3374a9936a0cSPeter Brune     } else {
33759566063dSJacob Faibussowitsch       PetscCall(SNESSetNormSchedule(snes->npc, SNES_NORM_NONE));
3376a9936a0cSPeter Brune     }
33779566063dSJacob Faibussowitsch     PetscCall(SNESSetFromOptions(snes->npc));
33786e2a1849SPeter Brune 
33796e2a1849SPeter Brune     /* copy the line search context over */
3380d8d34be6SBarry Smith     if (snes->linesearch && snes->npc->linesearch) {
33819566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes, &linesearch));
33829566063dSJacob Faibussowitsch       PetscCall(SNESGetLineSearch(snes->npc, &pclinesearch));
33839566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPreCheck(linesearch, &precheck, &lsprectx));
33849566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchGetPostCheck(linesearch, &postcheck, &lspostctx));
33859566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPreCheck(pclinesearch, precheck, lsprectx));
33869566063dSJacob Faibussowitsch       PetscCall(SNESLineSearchSetPostCheck(pclinesearch, postcheck, lspostctx));
33879566063dSJacob Faibussowitsch       PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch));
33886e2a1849SPeter Brune     }
3389d8d34be6SBarry Smith   }
33901baa6e33SBarry Smith   if (snes->mf) PetscCall(SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version));
33919927e4dfSBarry Smith   if (snes->ops->usercompute && !snes->user) PetscCallBack("SNES callback compute application context", (*snes->ops->usercompute)(snes, (void **)&snes->user));
33926e2a1849SPeter Brune 
339337ec4e1aSPeter Brune   snes->jac_iter = 0;
339437ec4e1aSPeter Brune   snes->pre_iter = 0;
339537ec4e1aSPeter Brune 
3396dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, setup);
339758c9b817SLisandro Dalcin 
33989566063dSJacob Faibussowitsch   PetscCall(SNESSetDefaultComputeJacobian(snes));
339958b371f3SBarry Smith 
3400b552625fSStefano Zampini   if (snes->npc && snes->npcside == PC_LEFT) {
34016c67d002SPeter Brune     if (snes->functype == SNES_FUNCTION_PRECONDITIONED) {
3402d8d34be6SBarry Smith       if (snes->linesearch) {
34039566063dSJacob Faibussowitsch         PetscCall(SNESGetLineSearch(snes, &linesearch));
34049566063dSJacob Faibussowitsch         PetscCall(SNESLineSearchSetFunction(linesearch, SNESComputeFunctionDefaultNPC));
34056c67d002SPeter Brune       }
34066c67d002SPeter Brune     }
3407d8d34be6SBarry Smith   }
3408fc8bc0e3SRichard Tran Mills   PetscCall(PetscLogEventEnd(SNES_SetUp, snes, 0, 0, 0));
34097aaed0d8SBarry Smith   snes->setupcalled = PETSC_TRUE;
34103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34119b94acceSBarry Smith }
34129b94acceSBarry Smith 
341337596af1SLisandro Dalcin /*@
3414*0b4b7b1cSBarry Smith   SNESReset - Resets a `SNES` context to the state it was in before `SNESSetUp()` was called and removes any allocated `Vec` and `Mat` from its data structures
341537596af1SLisandro Dalcin 
3416c3339decSBarry Smith   Collective
341737596af1SLisandro Dalcin 
341837596af1SLisandro Dalcin   Input Parameter:
3419*0b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
342037596af1SLisandro Dalcin 
3421d25893d9SBarry Smith   Level: intermediate
3422d25893d9SBarry Smith 
342395452b02SPatrick Sanan   Notes:
3424*0b4b7b1cSBarry Smith   Any options set on the `SNES` object, including those set with `SNESSetFromOptions()` remain.
3425*0b4b7b1cSBarry Smith 
3426f6dfbefdSBarry Smith   Call this if you wish to reuse a `SNES` but with different size vectors
342737596af1SLisandro Dalcin 
3428f6dfbefdSBarry Smith   Also calls the application context destroy routine set with `SNESSetComputeApplicationContext()`
3429f6dfbefdSBarry Smith 
34301cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESDestroy()`, `SNESCreate()`, `SNESSetUp()`, `SNESSolve()`
343137596af1SLisandro Dalcin @*/
3432d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESReset(SNES snes)
3433d71ae5a4SJacob Faibussowitsch {
343437596af1SLisandro Dalcin   PetscFunctionBegin;
343537596af1SLisandro Dalcin   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3436d25893d9SBarry Smith   if (snes->ops->userdestroy && snes->user) {
34379927e4dfSBarry Smith     PetscCallBack("SNES callback destroy application context", (*snes->ops->userdestroy)((void **)&snes->user));
34380298fd71SBarry Smith     snes->user = NULL;
3439d25893d9SBarry Smith   }
34401baa6e33SBarry Smith   if (snes->npc) PetscCall(SNESReset(snes->npc));
34418a23116dSBarry Smith 
3442dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, reset);
34431baa6e33SBarry Smith   if (snes->ksp) PetscCall(KSPReset(snes->ksp));
34449e764e56SPeter Brune 
34451baa6e33SBarry Smith   if (snes->linesearch) PetscCall(SNESLineSearchReset(snes->linesearch));
34469e764e56SPeter Brune 
34479566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_rhs));
34489566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
34499566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol_update));
34509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_func));
34519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian));
34529566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->jacobian_pre));
34539566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&snes->picard));
34549566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
34559566063dSJacob Faibussowitsch   PetscCall(VecDestroyVecs(snes->nvwork, &snes->vwork));
3456f5af7f23SKarl Rupp 
345740fdac6aSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_FALSE;
345840fdac6aSLawrence Mitchell 
345937596af1SLisandro Dalcin   snes->nwork = snes->nvwork = 0;
346037596af1SLisandro Dalcin   snes->setupcalled          = PETSC_FALSE;
34613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346237596af1SLisandro Dalcin }
346337596af1SLisandro Dalcin 
346452baeb72SSatish Balay /*@
346536d43d94SBarry Smith   SNESConvergedReasonViewCancel - Clears all the reason view functions for a `SNES` object provided with `SNESConvergedReasonViewSet()` also
346636d43d94SBarry Smith   removes the default viewer.
3467c4421ceaSFande Kong 
3468c3339decSBarry Smith   Collective
3469c4421ceaSFande Kong 
3470c4421ceaSFande Kong   Input Parameter:
3471*0b4b7b1cSBarry Smith . snes - the nonlinear iterative solver context obtained from `SNESCreate()`
3472c4421ceaSFande Kong 
3473c4421ceaSFande Kong   Level: intermediate
3474c4421ceaSFande Kong 
3475420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESReset()`, `SNESConvergedReasonViewSet()`
3476c4421ceaSFande Kong @*/
3477d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewCancel(SNES snes)
3478d71ae5a4SJacob Faibussowitsch {
3479c4421ceaSFande Kong   PetscInt i;
3480c4421ceaSFande Kong 
3481c4421ceaSFande Kong   PetscFunctionBegin;
3482c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3483c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
348448a46eb9SPierre Jolivet     if (snes->reasonviewdestroy[i]) PetscCall((*snes->reasonviewdestroy[i])(&snes->reasonviewcontext[i]));
3485c4421ceaSFande Kong   }
3486c4421ceaSFande Kong   snes->numberreasonviews = 0;
3487648c30bcSBarry Smith   PetscCall(PetscViewerDestroy(&snes->convergedreasonviewer));
34883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3489c4421ceaSFande Kong }
3490c4421ceaSFande Kong 
34910764c050SBarry Smith /*@
34929b94acceSBarry Smith   SNESDestroy - Destroys the nonlinear solver context that was created
3493f6dfbefdSBarry Smith   with `SNESCreate()`.
34949b94acceSBarry Smith 
3495c3339decSBarry Smith   Collective
3496c7afd0dbSLois Curfman McInnes 
34979b94acceSBarry Smith   Input Parameter:
3498f6dfbefdSBarry Smith . snes - the `SNES` context
34999b94acceSBarry Smith 
350036851e7fSLois Curfman McInnes   Level: beginner
350136851e7fSLois Curfman McInnes 
35021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESSolve()`
35039b94acceSBarry Smith @*/
3504d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESDestroy(SNES *snes)
3505d71ae5a4SJacob Faibussowitsch {
35063a40ed3dSBarry Smith   PetscFunctionBegin;
35073ba16761SJacob Faibussowitsch   if (!*snes) PetscFunctionReturn(PETSC_SUCCESS);
3508f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*snes, SNES_CLASSID, 1);
3509f4f49eeaSPierre Jolivet   if (--((PetscObject)*snes)->refct > 0) {
35109371c9d4SSatish Balay     *snes = NULL;
35113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
35129371c9d4SSatish Balay   }
3513d4bb536fSBarry Smith 
3514f4f49eeaSPierre Jolivet   PetscCall(SNESReset(*snes));
35159566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&(*snes)->npc));
35166b8b9a38SLisandro Dalcin 
3517e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
35189566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*snes));
3519f4f49eeaSPierre Jolivet   PetscTryTypeMethod(*snes, destroy);
35206d4c513bSLisandro Dalcin 
35219566063dSJacob Faibussowitsch   if ((*snes)->dm) PetscCall(DMCoarsenHookRemove((*snes)->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, *snes));
35229566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*snes)->dm));
35239566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&(*snes)->ksp));
35249566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&(*snes)->linesearch));
35256b8b9a38SLisandro Dalcin 
35269566063dSJacob Faibussowitsch   PetscCall(PetscFree((*snes)->kspconvctx));
352748a46eb9SPierre Jolivet   if ((*snes)->ops->convergeddestroy) PetscCall((*(*snes)->ops->convergeddestroy)((*snes)->cnvP));
352848a46eb9SPierre Jolivet   if ((*snes)->conv_hist_alloc) PetscCall(PetscFree2((*snes)->conv_hist, (*snes)->conv_hist_its));
3529f4f49eeaSPierre Jolivet   PetscCall(SNESMonitorCancel(*snes));
3530f4f49eeaSPierre Jolivet   PetscCall(SNESConvergedReasonViewCancel(*snes));
35319566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(snes));
35323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35339b94acceSBarry Smith }
35349b94acceSBarry Smith 
35359b94acceSBarry Smith /* ----------- Routines to set solver parameters ---------- */
35369b94acceSBarry Smith 
3537a8054027SBarry Smith /*@
3538*0b4b7b1cSBarry Smith   SNESSetLagPreconditioner - Sets when the preconditioner is rebuilt in the nonlinear solve `SNESSolve()`.
3539a8054027SBarry Smith 
3540c3339decSBarry Smith   Logically Collective
3541a8054027SBarry Smith 
3542a8054027SBarry Smith   Input Parameters:
3543f6dfbefdSBarry Smith + snes - the `SNES` context
3544d8e291bfSBarry Smith - lag  - 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time
35453b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3546a8054027SBarry Smith 
3547a8054027SBarry Smith   Options Database Keys:
3548420bcc1bSBarry Smith + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple `SNESSolve()`
35493d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
3550420bcc1bSBarry Smith . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple `SNESSolve()`
35513d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
3552a8054027SBarry Smith 
3553dc4c0fb0SBarry Smith   Level: intermediate
3554dc4c0fb0SBarry Smith 
3555420bcc1bSBarry Smith   Notes:
3556a8054027SBarry Smith   The default is 1
3557420bcc1bSBarry Smith 
3558f6dfbefdSBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagPreconditionerPersists()` was called
3559d8e291bfSBarry Smith 
3560f6dfbefdSBarry Smith   `SNESSetLagPreconditionerPersists()` allows using the same uniform lagging (for example every second linear solve) across multiple nonlinear solves.
3561a8054027SBarry Smith 
35623201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetLagPreconditionerPersists()`,
3563f6dfbefdSBarry Smith           `SNESSetLagJacobianPersists()`, `SNES`, `SNESSolve()`
3564a8054027SBarry Smith @*/
3565d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditioner(SNES snes, PetscInt lag)
3566d71ae5a4SJacob Faibussowitsch {
3567a8054027SBarry Smith   PetscFunctionBegin;
35680700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
35695f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
35705f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3571c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3572a8054027SBarry Smith   snes->lagpreconditioner = lag;
35733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3574a8054027SBarry Smith }
3575a8054027SBarry Smith 
3576efd51863SBarry Smith /*@
3577f6dfbefdSBarry Smith   SNESSetGridSequence - sets the number of steps of grid sequencing that `SNES` will do
3578efd51863SBarry Smith 
3579c3339decSBarry Smith   Logically Collective
3580efd51863SBarry Smith 
3581efd51863SBarry Smith   Input Parameters:
3582f6dfbefdSBarry Smith + snes  - the `SNES` context
3583efd51863SBarry Smith - steps - the number of refinements to do, defaults to 0
3584efd51863SBarry Smith 
3585f6dfbefdSBarry Smith   Options Database Key:
358667b8a455SSatish Balay . -snes_grid_sequence <steps> - Use grid sequencing to generate initial guess
3587efd51863SBarry Smith 
3588efd51863SBarry Smith   Level: intermediate
3589efd51863SBarry Smith 
3590*0b4b7b1cSBarry Smith   Notes:
3591*0b4b7b1cSBarry Smith   Once grid sequencing is turned on `SNESSolve()` will automatically perform the solve on each grid refinement.
3592*0b4b7b1cSBarry Smith 
3593f6dfbefdSBarry Smith   Use `SNESGetSolution()` to extract the fine grid solution after grid sequencing.
3594c0df2a02SJed Brown 
35953201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetGridSequence()`,
3596*0b4b7b1cSBarry Smith           `SNESetDM()`, `SNESSolve()`
3597efd51863SBarry Smith @*/
3598d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetGridSequence(SNES snes, PetscInt steps)
3599d71ae5a4SJacob Faibussowitsch {
3600efd51863SBarry Smith   PetscFunctionBegin;
3601efd51863SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3602efd51863SBarry Smith   PetscValidLogicalCollectiveInt(snes, steps, 2);
3603efd51863SBarry Smith   snes->gridsequence = steps;
36043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3605efd51863SBarry Smith }
3606efd51863SBarry Smith 
3607fa19ca70SBarry Smith /*@
3608f6dfbefdSBarry Smith   SNESGetGridSequence - gets the number of steps of grid sequencing that `SNES` will do
3609fa19ca70SBarry Smith 
3610c3339decSBarry Smith   Logically Collective
3611fa19ca70SBarry Smith 
3612fa19ca70SBarry Smith   Input Parameter:
3613f6dfbefdSBarry Smith . snes - the `SNES` context
3614fa19ca70SBarry Smith 
3615fa19ca70SBarry Smith   Output Parameter:
3616fa19ca70SBarry Smith . steps - the number of refinements to do, defaults to 0
3617fa19ca70SBarry Smith 
3618fa19ca70SBarry Smith   Level: intermediate
3619fa19ca70SBarry Smith 
36203201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESGetLagPreconditioner()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESSetGridSequence()`
3621fa19ca70SBarry Smith @*/
3622d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetGridSequence(SNES snes, PetscInt *steps)
3623d71ae5a4SJacob Faibussowitsch {
3624fa19ca70SBarry Smith   PetscFunctionBegin;
3625fa19ca70SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3626fa19ca70SBarry Smith   *steps = snes->gridsequence;
36273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3628fa19ca70SBarry Smith }
3629fa19ca70SBarry Smith 
3630a8054027SBarry Smith /*@
3631f6dfbefdSBarry Smith   SNESGetLagPreconditioner - Return how often the preconditioner is rebuilt
3632a8054027SBarry Smith 
36333f9fe445SBarry Smith   Not Collective
3634a8054027SBarry Smith 
3635a8054027SBarry Smith   Input Parameter:
3636f6dfbefdSBarry Smith . snes - the `SNES` context
3637a8054027SBarry Smith 
3638a8054027SBarry Smith   Output Parameter:
3639a8054027SBarry 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
36403b4f5425SBarry Smith          the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that
3641a8054027SBarry Smith 
3642dc4c0fb0SBarry Smith   Level: intermediate
3643dc4c0fb0SBarry Smith 
3644a8054027SBarry Smith   Notes:
3645a8054027SBarry Smith   The default is 1
3646f6dfbefdSBarry Smith 
3647a8054027SBarry Smith   The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3648a8054027SBarry Smith 
36493201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3650a8054027SBarry Smith @*/
3651d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagPreconditioner(SNES snes, PetscInt *lag)
3652d71ae5a4SJacob Faibussowitsch {
3653a8054027SBarry Smith   PetscFunctionBegin;
36540700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3655a8054027SBarry Smith   *lag = snes->lagpreconditioner;
36563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3657a8054027SBarry Smith }
3658a8054027SBarry Smith 
3659e35cf81dSBarry Smith /*@
3660f6dfbefdSBarry Smith   SNESSetLagJacobian - Set when the Jacobian is rebuilt in the nonlinear solve. See `SNESSetLagPreconditioner()` for determining how
3661e35cf81dSBarry Smith   often the preconditioner is rebuilt.
3662e35cf81dSBarry Smith 
3663c3339decSBarry Smith   Logically Collective
3664e35cf81dSBarry Smith 
3665e35cf81dSBarry Smith   Input Parameters:
3666f6dfbefdSBarry Smith + snes - the `SNES` context
3667e35cf81dSBarry 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
3668fe3ffe1eSBarry Smith          the Jacobian is built etc. -2 means rebuild at next chance but then never again
3669e35cf81dSBarry Smith 
3670e35cf81dSBarry Smith   Options Database Keys:
367179a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
36723d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
367379a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
36743d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag.
3675e35cf81dSBarry Smith 
3676dc4c0fb0SBarry Smith   Level: intermediate
3677dc4c0fb0SBarry Smith 
3678e35cf81dSBarry Smith   Notes:
3679e35cf81dSBarry Smith   The default is 1
3680f6dfbefdSBarry Smith 
3681e35cf81dSBarry Smith   The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1
3682f6dfbefdSBarry Smith 
3683fe3ffe1eSBarry 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
3684fe3ffe1eSBarry Smith   at the next Newton step but never again (unless it is reset to another value)
3685e35cf81dSBarry Smith 
36863201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESGetLagPreconditioner()`, `SNESSetLagPreconditioner()`, `SNESGetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3687e35cf81dSBarry Smith @*/
3688d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobian(SNES snes, PetscInt lag)
3689d71ae5a4SJacob Faibussowitsch {
3690e35cf81dSBarry Smith   PetscFunctionBegin;
36910700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
36925f80ce2aSJacob Faibussowitsch   PetscCheck(lag >= -2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag must be -2, -1, 1 or greater");
36935f80ce2aSJacob Faibussowitsch   PetscCheck(lag, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lag cannot be 0");
3694c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, lag, 2);
3695e35cf81dSBarry Smith   snes->lagjacobian = lag;
36963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3697e35cf81dSBarry Smith }
3698e35cf81dSBarry Smith 
3699e35cf81dSBarry Smith /*@
3700f6dfbefdSBarry Smith   SNESGetLagJacobian - Get how often the Jacobian is rebuilt. See `SNESGetLagPreconditioner()` to determine when the preconditioner is rebuilt
3701e35cf81dSBarry Smith 
37023f9fe445SBarry Smith   Not Collective
3703e35cf81dSBarry Smith 
3704e35cf81dSBarry Smith   Input Parameter:
3705f6dfbefdSBarry Smith . snes - the `SNES` context
3706e35cf81dSBarry Smith 
3707e35cf81dSBarry Smith   Output Parameter:
3708e35cf81dSBarry 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
3709e35cf81dSBarry Smith          the Jacobian is built etc.
3710e35cf81dSBarry Smith 
3711dc4c0fb0SBarry Smith   Level: intermediate
3712dc4c0fb0SBarry Smith 
3713e35cf81dSBarry Smith   Notes:
3714e35cf81dSBarry Smith   The default is 1
3715f6dfbefdSBarry Smith 
3716f6dfbefdSBarry Smith   The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 or `SNESSetLagJacobianPersists()` was called.
3717e35cf81dSBarry Smith 
37183201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobian()`, `SNESSetLagPreconditioner()`, `SNESGetLagPreconditioner()`, `SNESSetLagJacobianPersists()`, `SNESSetLagPreconditionerPersists()`
3719e35cf81dSBarry Smith 
3720e35cf81dSBarry Smith @*/
3721d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLagJacobian(SNES snes, PetscInt *lag)
3722d71ae5a4SJacob Faibussowitsch {
3723e35cf81dSBarry Smith   PetscFunctionBegin;
37240700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3725e35cf81dSBarry Smith   *lag = snes->lagjacobian;
37263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3727e35cf81dSBarry Smith }
3728e35cf81dSBarry Smith 
372937ec4e1aSPeter Brune /*@
3730f6dfbefdSBarry Smith   SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple nonlinear solves
373137ec4e1aSPeter Brune 
3732c3339decSBarry Smith   Logically collective
373337ec4e1aSPeter Brune 
3734d8d19677SJose E. Roman   Input Parameters:
3735f6dfbefdSBarry Smith + snes - the `SNES` context
37369d7e2deaSPeter Brune - flg  - jacobian lagging persists if true
373737ec4e1aSPeter Brune 
373837ec4e1aSPeter Brune   Options Database Keys:
373979a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37403d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
374179a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37423d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
37433d5a8a6aSBarry Smith 
3744dc4c0fb0SBarry Smith   Level: advanced
3745dc4c0fb0SBarry Smith 
374695452b02SPatrick Sanan   Notes:
3747420bcc1bSBarry Smith   Normally when `SNESSetLagJacobian()` is used, the Jacobian is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3748f6dfbefdSBarry Smith 
374995452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by
375037ec4e1aSPeter Brune   several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several
375137ec4e1aSPeter Brune   timesteps may present huge efficiency gains.
375237ec4e1aSPeter Brune 
375342747ad1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSetLagPreconditionerPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`
375437ec4e1aSPeter Brune @*/
3755d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagJacobianPersists(SNES snes, PetscBool flg)
3756d71ae5a4SJacob Faibussowitsch {
375737ec4e1aSPeter Brune   PetscFunctionBegin;
375837ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
375937ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
376037ec4e1aSPeter Brune   snes->lagjac_persist = flg;
37613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
376237ec4e1aSPeter Brune }
376337ec4e1aSPeter Brune 
376437ec4e1aSPeter Brune /*@
3765d8e291bfSBarry Smith   SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple nonlinear solves
376637ec4e1aSPeter Brune 
3767c3339decSBarry Smith   Logically Collective
376837ec4e1aSPeter Brune 
3769d8d19677SJose E. Roman   Input Parameters:
3770f6dfbefdSBarry Smith + snes - the `SNES` context
37719d7e2deaSPeter Brune - flg  - preconditioner lagging persists if true
377237ec4e1aSPeter Brune 
377337ec4e1aSPeter Brune   Options Database Keys:
377479a4f3cfSmarkadams4 + -snes_lag_jacobian_persists <true,false>       - sets the persistence through multiple SNES solves
37753d5a8a6aSBarry Smith . -snes_lag_jacobian <-2,1,2,...>                - sets the lag
377679a4f3cfSmarkadams4 . -snes_lag_preconditioner_persists <true,false> - sets the persistence through multiple SNES solves
37773d5a8a6aSBarry Smith - -snes_lag_preconditioner <-2,1,2,...>          - sets the lag
377837ec4e1aSPeter Brune 
3779dc4c0fb0SBarry Smith   Level: developer
3780dc4c0fb0SBarry Smith 
378195452b02SPatrick Sanan   Notes:
3782420bcc1bSBarry Smith   Normally when `SNESSetLagPreconditioner()` is used, the preconditioner is always rebuilt at the beginning of each new nonlinear solve, this removes that behavior
3783f6dfbefdSBarry Smith 
378495452b02SPatrick Sanan   This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale
378537ec4e1aSPeter Brune   by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over
378637ec4e1aSPeter Brune   several timesteps may present huge efficiency gains.
378737ec4e1aSPeter Brune 
37881cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetLagJacobianPersists()`, `SNESSetLagJacobian()`, `SNESGetLagJacobian()`, `SNESGetNPC()`, `SNESSetLagPreconditioner()`
378937ec4e1aSPeter Brune @*/
3790d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes, PetscBool flg)
3791d71ae5a4SJacob Faibussowitsch {
379237ec4e1aSPeter Brune   PetscFunctionBegin;
379337ec4e1aSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
379437ec4e1aSPeter Brune   PetscValidLogicalCollectiveBool(snes, flg, 2);
379537ec4e1aSPeter Brune   snes->lagpre_persist = flg;
37963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
379737ec4e1aSPeter Brune }
379837ec4e1aSPeter Brune 
37999b94acceSBarry Smith /*@
3800f6dfbefdSBarry Smith   SNESSetForceIteration - force `SNESSolve()` to take at least one iteration regardless of the initial residual norm
3801be5caee7SBarry Smith 
3802c3339decSBarry Smith   Logically Collective
3803be5caee7SBarry Smith 
3804be5caee7SBarry Smith   Input Parameters:
3805f6dfbefdSBarry Smith + snes  - the `SNES` context
3806f6dfbefdSBarry Smith - force - `PETSC_TRUE` require at least one iteration
3807be5caee7SBarry Smith 
3808f6dfbefdSBarry Smith   Options Database Key:
3809be5caee7SBarry Smith . -snes_force_iteration <force> - Sets forcing an iteration
3810be5caee7SBarry Smith 
3811dc4c0fb0SBarry Smith   Level: intermediate
3812dc4c0fb0SBarry Smith 
3813f6dfbefdSBarry Smith   Note:
3814f6dfbefdSBarry Smith   This is used sometimes with `TS` to prevent `TS` from detecting a false steady state solution
3815be5caee7SBarry Smith 
38163201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `TS`, `SNESSetDivergenceTolerance()`
3817be5caee7SBarry Smith @*/
3818d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetForceIteration(SNES snes, PetscBool force)
3819d71ae5a4SJacob Faibussowitsch {
3820be5caee7SBarry Smith   PetscFunctionBegin;
3821be5caee7SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3822be5caee7SBarry Smith   snes->forceiteration = force;
38233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3824be5caee7SBarry Smith }
3825be5caee7SBarry Smith 
382685216dc7SFande Kong /*@
3827f6dfbefdSBarry Smith   SNESGetForceIteration - Check whether or not `SNESSolve()` take at least one iteration regardless of the initial residual norm
382885216dc7SFande Kong 
3829c3339decSBarry Smith   Logically Collective
383085216dc7SFande Kong 
38312fe279fdSBarry Smith   Input Parameter:
3832f6dfbefdSBarry Smith . snes - the `SNES` context
383385216dc7SFande Kong 
383485216dc7SFande Kong   Output Parameter:
3835dc4c0fb0SBarry Smith . force - `PETSC_TRUE` requires at least one iteration.
383685216dc7SFande Kong 
383706dd6b0eSSatish Balay   Level: intermediate
383806dd6b0eSSatish Balay 
38393201ab8dSStefano Zampini .seealso: [](ch_snes), `SNES`, `SNESSetForceIteration()`, `SNESSetDivergenceTolerance()`
384085216dc7SFande Kong @*/
3841d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetForceIteration(SNES snes, PetscBool *force)
3842d71ae5a4SJacob Faibussowitsch {
384385216dc7SFande Kong   PetscFunctionBegin;
384485216dc7SFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
384585216dc7SFande Kong   *force = snes->forceiteration;
38463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
384785216dc7SFande Kong }
3848be5caee7SBarry Smith 
3849be5caee7SBarry Smith /*@
3850*0b4b7b1cSBarry Smith   SNESSetTolerances - Sets various parameters used in `SNES` convergence tests.
38519b94acceSBarry Smith 
3852c3339decSBarry Smith   Logically Collective
3853c7afd0dbSLois Curfman McInnes 
38549b94acceSBarry Smith   Input Parameters:
3855f6dfbefdSBarry Smith + snes   - the `SNES` context
3856*0b4b7b1cSBarry Smith . abstol - the absolute convergence tolerance, $ F(x^n) \le abstol $
3857*0b4b7b1cSBarry Smith . rtol   - the relative convergence tolerance, $ F(x^n) \le reltol * F(x^0) $
38585358d0d4SBarry Smith . stol   - convergence tolerance in terms of the norm of the change in the solution between steps,  || delta x || < stol*|| x ||
3859*0b4b7b1cSBarry Smith . maxit  - the maximum number of iterations allowed in the solver, default 50.
3860*0b4b7b1cSBarry Smith - maxf   - the maximum number of function evaluations allowed in the solver (use `PETSC_UNLIMITED` indicates no limit), default 10,000
3861fee21e36SBarry Smith 
386233174efeSLois Curfman McInnes   Options Database Keys:
386377e5a1f9SBarry Smith + -snes_atol <abstol>    - Sets `abstol`
386477e5a1f9SBarry Smith . -snes_rtol <rtol>      - Sets `rtol`
386577e5a1f9SBarry Smith . -snes_stol <stol>      - Sets `stol`
386677e5a1f9SBarry Smith . -snes_max_it <maxit>   - Sets `maxit`
386777e5a1f9SBarry Smith - -snes_max_funcs <maxf> - Sets `maxf` (use `unlimited` to have no maximum)
38689b94acceSBarry Smith 
386936851e7fSLois Curfman McInnes   Level: intermediate
387036851e7fSLois Curfman McInnes 
387177e5a1f9SBarry Smith   Note:
387277e5a1f9SBarry Smith   All parameters must be non-negative
387377e5a1f9SBarry Smith 
387477e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the current value of any parameter and `PETSC_DETERMINE` to use the default value for the given `SNES`.
387577e5a1f9SBarry Smith   The default value is the value in the object when its type is set.
387677e5a1f9SBarry Smith 
387777e5a1f9SBarry Smith   Use `PETSC_UNLIMITED` on `maxit` or `maxf` to indicate there is no bound on the number of iterations or number of function evaluations.
387877e5a1f9SBarry Smith 
387977e5a1f9SBarry Smith   Fortran Note:
388077e5a1f9SBarry Smith   Use `PETSC_CURRENT_INTEGER`, `PETSC_CURRENT_REAL`, `PETSC_UNLIMITED_INTEGER`, `PETSC_DETERMINE_INTEGER`, or `PETSC_DETERMINE_REAL`
388177e5a1f9SBarry Smith 
38823201ab8dSStefano Zampini .seealso: [](ch_snes), `SNESSolve()`, `SNES`, `SNESSetDivergenceTolerance()`, `SNESSetForceIteration()`
38839b94acceSBarry Smith @*/
3884d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetTolerances(SNES snes, PetscReal abstol, PetscReal rtol, PetscReal stol, PetscInt maxit, PetscInt maxf)
3885d71ae5a4SJacob Faibussowitsch {
38863a40ed3dSBarry Smith   PetscFunctionBegin;
38870700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3888c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, abstol, 2);
3889c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol, 3);
3890c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, stol, 4);
3891c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxit, 5);
3892c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, maxf, 6);
3893c5eb9154SBarry Smith 
389477e5a1f9SBarry Smith   if (abstol == (PetscReal)PETSC_DETERMINE) {
389577e5a1f9SBarry Smith     snes->abstol = snes->default_abstol;
389677e5a1f9SBarry Smith   } else if (abstol != (PetscReal)PETSC_CURRENT) {
38975f80ce2aSJacob Faibussowitsch     PetscCheck(abstol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)abstol);
3898ab54825eSJed Brown     snes->abstol = abstol;
3899ab54825eSJed Brown   }
390077e5a1f9SBarry Smith 
390177e5a1f9SBarry Smith   if (rtol == (PetscReal)PETSC_DETERMINE) {
390277e5a1f9SBarry Smith     snes->rtol = snes->default_rtol;
390377e5a1f9SBarry Smith   } else if (rtol != (PetscReal)PETSC_CURRENT) {
39045f80ce2aSJacob 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);
3905ab54825eSJed Brown     snes->rtol = rtol;
3906ab54825eSJed Brown   }
390777e5a1f9SBarry Smith 
390877e5a1f9SBarry Smith   if (stol == (PetscReal)PETSC_DETERMINE) {
390977e5a1f9SBarry Smith     snes->stol = snes->default_stol;
391077e5a1f9SBarry Smith   } else if (stol != (PetscReal)PETSC_CURRENT) {
39115f80ce2aSJacob Faibussowitsch     PetscCheck(stol >= 0.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Step tolerance %g must be non-negative", (double)stol);
3912c60f73f4SPeter Brune     snes->stol = stol;
3913ab54825eSJed Brown   }
391477e5a1f9SBarry Smith 
391577e5a1f9SBarry Smith   if (maxit == (PetscInt)PETSC_DETERMINE) {
391677e5a1f9SBarry Smith     snes->max_its = snes->default_max_its;
391777e5a1f9SBarry Smith   } else if (maxit == (PetscInt)PETSC_UNLIMITED) {
391877e5a1f9SBarry Smith     snes->max_its = PETSC_INT_MAX;
391977e5a1f9SBarry Smith   } else if (maxit != PETSC_CURRENT) {
392063a3b9bcSJacob Faibussowitsch     PetscCheck(maxit >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of iterations %" PetscInt_FMT " must be non-negative", maxit);
3921ab54825eSJed Brown     snes->max_its = maxit;
3922ab54825eSJed Brown   }
392377e5a1f9SBarry Smith 
392477e5a1f9SBarry Smith   if (maxf == (PetscInt)PETSC_DETERMINE) {
392577e5a1f9SBarry Smith     snes->max_funcs = snes->default_max_funcs;
392677e5a1f9SBarry Smith   } else if (maxf == (PetscInt)PETSC_UNLIMITED || maxf == -1) {
392777e5a1f9SBarry Smith     snes->max_funcs = PETSC_UNLIMITED;
392877e5a1f9SBarry Smith   } else if (maxf != PETSC_CURRENT) {
392977e5a1f9SBarry Smith     PetscCheck(maxf >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of function evaluations %" PetscInt_FMT " must be nonnegative", maxf);
3930ab54825eSJed Brown     snes->max_funcs = maxf;
3931ab54825eSJed Brown   }
39323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39339b94acceSBarry Smith }
39349b94acceSBarry Smith 
3935e4d06f11SPatrick Farrell /*@
3936f6dfbefdSBarry Smith   SNESSetDivergenceTolerance - Sets the divergence tolerance used for the `SNES` divergence test.
3937e4d06f11SPatrick Farrell 
3938c3339decSBarry Smith   Logically Collective
3939e4d06f11SPatrick Farrell 
3940e4d06f11SPatrick Farrell   Input Parameters:
3941f6dfbefdSBarry Smith + snes   - the `SNES` context
3942*0b4b7b1cSBarry Smith - divtol - the divergence tolerance. Use `PETSC_UNLIMITED` to deactivate the test. If the residual norm $ F(x^n) \ge divtol * F(x^0) $ the solver
3943*0b4b7b1cSBarry Smith            is stopped due to divergence.
3944e4d06f11SPatrick Farrell 
3945f6dfbefdSBarry Smith   Options Database Key:
3946dc4c0fb0SBarry Smith . -snes_divergence_tolerance <divtol> - Sets `divtol`
3947e4d06f11SPatrick Farrell 
3948e4d06f11SPatrick Farrell   Level: intermediate
3949e4d06f11SPatrick Farrell 
395077e5a1f9SBarry Smith   Notes:
395177e5a1f9SBarry Smith   Use `PETSC_DETERMINE` to use the default value from when the object's type was set.
3952e5cd489fSStefano Zampini 
395377e5a1f9SBarry Smith   Fortran Note:
395477e5a1f9SBarry Smith   Use ``PETSC_DETERMINE_REAL` or `PETSC_UNLIMITED_REAL`
395577e5a1f9SBarry Smith 
395677e5a1f9SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetTolerances()`, `SNESGetDivergenceTolerance()`
3957e4d06f11SPatrick Farrell @*/
3958d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDivergenceTolerance(SNES snes, PetscReal divtol)
3959d71ae5a4SJacob Faibussowitsch {
3960e4d06f11SPatrick Farrell   PetscFunctionBegin;
3961e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
3962e4d06f11SPatrick Farrell   PetscValidLogicalCollectiveReal(snes, divtol, 2);
396377e5a1f9SBarry Smith 
396477e5a1f9SBarry Smith   if (divtol == (PetscReal)PETSC_DETERMINE) {
396577e5a1f9SBarry Smith     snes->divtol = snes->default_divtol;
396677e5a1f9SBarry Smith   } else if (divtol == (PetscReal)PETSC_UNLIMITED || divtol == -1) {
396777e5a1f9SBarry Smith     snes->divtol = PETSC_UNLIMITED;
396877e5a1f9SBarry Smith   } else if (divtol != (PetscReal)PETSC_CURRENT) {
396977e5a1f9SBarry Smith     PetscCheck(divtol >= 1.0, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_OUTOFRANGE, "Divergence tolerance %g must be greater than 1.0", (double)divtol);
397077e5a1f9SBarry Smith     snes->divtol = divtol;
397177e5a1f9SBarry Smith   }
39723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3973e4d06f11SPatrick Farrell }
3974e4d06f11SPatrick Farrell 
39759b94acceSBarry Smith /*@
3976*0b4b7b1cSBarry Smith   SNESGetTolerances - Gets various parameters used in `SNES` convergence tests.
397733174efeSLois Curfman McInnes 
3978c7afd0dbSLois Curfman McInnes   Not Collective
3979c7afd0dbSLois Curfman McInnes 
398077e5a1f9SBarry Smith   Input Parameter:
398177e5a1f9SBarry Smith . snes - the `SNES` context
398277e5a1f9SBarry Smith 
398377e5a1f9SBarry Smith   Output Parameters:
3984*0b4b7b1cSBarry Smith + atol  - the absolute convergence tolerance
3985*0b4b7b1cSBarry Smith . rtol  - the relative convergence tolerance
398677e5a1f9SBarry Smith . stol  - convergence tolerance in terms of the norm of the change in the solution between steps
3987*0b4b7b1cSBarry Smith . maxit - the maximum number of iterations allowed
3988*0b4b7b1cSBarry Smith - maxf  - the maximum number of function evaluations allowed, `PETSC_UNLIMITED` indicates no bound
3989fee21e36SBarry Smith 
399036851e7fSLois Curfman McInnes   Level: intermediate
399136851e7fSLois Curfman McInnes 
3992*0b4b7b1cSBarry Smith   Notes:
3993*0b4b7b1cSBarry Smith   See `SNESSetTolerances()` for details on the parameters.
3994*0b4b7b1cSBarry Smith 
3995dc4c0fb0SBarry Smith   The user can specify `NULL` for any parameter that is not needed.
3996dc4c0fb0SBarry Smith 
39971cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetTolerances()`
399833174efeSLois Curfman McInnes @*/
3999d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetTolerances(SNES snes, PetscReal *atol, PetscReal *rtol, PetscReal *stol, PetscInt *maxit, PetscInt *maxf)
4000d71ae5a4SJacob Faibussowitsch {
40013a40ed3dSBarry Smith   PetscFunctionBegin;
40020700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
400385385478SLisandro Dalcin   if (atol) *atol = snes->abstol;
400433174efeSLois Curfman McInnes   if (rtol) *rtol = snes->rtol;
4005c60f73f4SPeter Brune   if (stol) *stol = snes->stol;
400633174efeSLois Curfman McInnes   if (maxit) *maxit = snes->max_its;
400733174efeSLois Curfman McInnes   if (maxf) *maxf = snes->max_funcs;
40083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
400933174efeSLois Curfman McInnes }
401033174efeSLois Curfman McInnes 
4011e4d06f11SPatrick Farrell /*@
4012e4d06f11SPatrick Farrell   SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test.
4013e4d06f11SPatrick Farrell 
4014e4d06f11SPatrick Farrell   Not Collective
4015e4d06f11SPatrick Farrell 
4016e4d06f11SPatrick Farrell   Input Parameters:
4017f6dfbefdSBarry Smith + snes   - the `SNES` context
4018e4d06f11SPatrick Farrell - divtol - divergence tolerance
4019e4d06f11SPatrick Farrell 
4020e4d06f11SPatrick Farrell   Level: intermediate
4021e4d06f11SPatrick Farrell 
40221cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetDivergenceTolerance()`
4023e4d06f11SPatrick Farrell @*/
4024d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDivergenceTolerance(SNES snes, PetscReal *divtol)
4025d71ae5a4SJacob Faibussowitsch {
4026e4d06f11SPatrick Farrell   PetscFunctionBegin;
4027e4d06f11SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4028e4d06f11SPatrick Farrell   if (divtol) *divtol = snes->divtol;
40293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4030e4d06f11SPatrick Farrell }
4031e4d06f11SPatrick Farrell 
40326ba87a44SLisandro Dalcin PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);
40336ba87a44SLisandro Dalcin 
4034d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorLGRange(SNES snes, PetscInt n, PetscReal rnorm, void *monctx)
4035d71ae5a4SJacob Faibussowitsch {
4036b271bb04SBarry Smith   PetscDrawLG      lg;
4037b271bb04SBarry Smith   PetscReal        x, y, per;
4038b271bb04SBarry Smith   PetscViewer      v = (PetscViewer)monctx;
4039b271bb04SBarry Smith   static PetscReal prev; /* should be in the context */
4040b271bb04SBarry Smith   PetscDraw        draw;
4041b271bb04SBarry Smith 
4042459f5d12SBarry Smith   PetscFunctionBegin;
40434d4332d5SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 4);
40449566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
40459566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40469566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40479566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
4048b271bb04SBarry Smith   x = (PetscReal)n;
404977b4d14cSPeter Brune   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
405094c9c6d3SKarl Rupp   else y = -15.0;
40519566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40526934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40539566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40549566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4055b271bb04SBarry Smith   }
4056b271bb04SBarry Smith 
40579566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
40589566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40599566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
4060aaa8cc7dSPierre Jolivet   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
40619566063dSJacob Faibussowitsch   PetscCall(SNESMonitorRange_Private(snes, n, &per));
4062b271bb04SBarry Smith   x = (PetscReal)n;
4063b271bb04SBarry Smith   y = 100.0 * per;
40649566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40656934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40669566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40679566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4068b271bb04SBarry Smith   }
4069b271bb04SBarry Smith 
40709566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
40719371c9d4SSatish Balay   if (!n) {
40729371c9d4SSatish Balay     prev = rnorm;
40739371c9d4SSatish Balay     PetscCall(PetscDrawLGReset(lg));
40749371c9d4SSatish Balay   }
40759566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40769566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm"));
4077b271bb04SBarry Smith   x = (PetscReal)n;
4078b271bb04SBarry Smith   y = (prev - rnorm) / prev;
40799566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
40806934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40819566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40829566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4083b271bb04SBarry Smith   }
4084b271bb04SBarry Smith 
40859566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
40869566063dSJacob Faibussowitsch   if (!n) PetscCall(PetscDrawLGReset(lg));
40879566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGGetDraw(lg, &draw));
40889566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "(norm -oldnorm)/oldnorm*(% > .2 max)"));
4089b271bb04SBarry Smith   x = (PetscReal)n;
4090b271bb04SBarry Smith   y = (prev - rnorm) / (prev * per);
4091b271bb04SBarry Smith   if (n > 2) { /*skip initial crazy value */
40929566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
4093b271bb04SBarry Smith   }
40946934998bSLisandro Dalcin   if (n < 20 || !(n % 5) || snes->reason) {
40959566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGDraw(lg));
40969566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGSave(lg));
4097b271bb04SBarry Smith   }
4098b271bb04SBarry Smith   prev = rnorm;
40993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4100b271bb04SBarry Smith }
4101b271bb04SBarry Smith 
4102228d79bcSJed Brown /*@
41032d157150SStefano Zampini   SNESConverged - Run the convergence test and update the `SNESConvergedReason`.
41042d157150SStefano Zampini 
41052d157150SStefano Zampini   Collective
41062d157150SStefano Zampini 
41072d157150SStefano Zampini   Input Parameters:
41082d157150SStefano Zampini + snes  - the `SNES` context
41092d157150SStefano Zampini . it    - current iteration
41102d157150SStefano Zampini . xnorm - 2-norm of current iterate
41112d157150SStefano Zampini . snorm - 2-norm of current step
41122d157150SStefano Zampini - fnorm - 2-norm of function
41132d157150SStefano Zampini 
41142d157150SStefano Zampini   Level: developer
41152d157150SStefano Zampini 
41162d157150SStefano Zampini   Note:
4117420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
41182d157150SStefano Zampini   It does not typically need to be called by the user.
41192d157150SStefano Zampini 
4120be50c303SSatish Balay .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
41212d157150SStefano Zampini @*/
41222d157150SStefano Zampini PetscErrorCode SNESConverged(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm)
41232d157150SStefano Zampini {
41242d157150SStefano Zampini   PetscFunctionBegin;
41252d157150SStefano Zampini   if (!snes->reason) {
41262d157150SStefano Zampini     if (snes->normschedule == SNES_NORM_ALWAYS) PetscUseTypeMethod(snes, converged, it, xnorm, snorm, fnorm, &snes->reason, snes->cnvP);
41272d157150SStefano Zampini     if (it == snes->max_its && !snes->reason) {
41282d157150SStefano Zampini       if (snes->normschedule == SNES_NORM_ALWAYS) {
41292d157150SStefano Zampini         PetscCall(PetscInfo(snes, "Maximum number of iterations has been reached: %" PetscInt_FMT "\n", snes->max_its));
41302d157150SStefano Zampini         snes->reason = SNES_DIVERGED_MAX_IT;
41312d157150SStefano Zampini       } else snes->reason = SNES_CONVERGED_ITS;
41322d157150SStefano Zampini     }
41332d157150SStefano Zampini   }
41342d157150SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
41352d157150SStefano Zampini }
41362d157150SStefano Zampini 
41372d157150SStefano Zampini /*@
4138*0b4b7b1cSBarry Smith   SNESMonitor - runs any `SNES` monitor routines provided with `SNESMonitor()` or the options database
4139228d79bcSJed Brown 
4140c3339decSBarry Smith   Collective
4141228d79bcSJed Brown 
4142228d79bcSJed Brown   Input Parameters:
4143f6dfbefdSBarry Smith + snes  - nonlinear solver context obtained from `SNESCreate()`
4144*0b4b7b1cSBarry Smith . iter  - current iteration number
4145*0b4b7b1cSBarry Smith - rnorm - current relative norm of the residual
4146228d79bcSJed Brown 
4147dc4c0fb0SBarry Smith   Level: developer
4148dc4c0fb0SBarry Smith 
4149f6dfbefdSBarry Smith   Note:
4150420bcc1bSBarry Smith   This routine is called by the `SNESSolve()` implementations.
4151228d79bcSJed Brown   It does not typically need to be called by the user.
4152228d79bcSJed Brown 
41531cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`
4154228d79bcSJed Brown @*/
4155d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitor(SNES snes, PetscInt iter, PetscReal rnorm)
4156d71ae5a4SJacob Faibussowitsch {
41577a03ce2fSLisandro Dalcin   PetscInt i, n = snes->numbermonitors;
41587a03ce2fSLisandro Dalcin 
41597a03ce2fSLisandro Dalcin   PetscFunctionBegin;
41605f3c5e7aSBarry Smith   if (n > 0) SNESCheckFunctionNorm(snes, rnorm);
41619566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(snes->vec_sol));
416248a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall((*snes->monitor[i])(snes, iter, rnorm, snes->monitorcontext[i]));
41639566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(snes->vec_sol));
41643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41657a03ce2fSLisandro Dalcin }
41667a03ce2fSLisandro Dalcin 
41679b94acceSBarry Smith /* ------------ Routines to set performance monitoring options ----------- */
41689b94acceSBarry Smith 
4169bf388a1fSBarry Smith /*MC
4170f6dfbefdSBarry Smith     SNESMonitorFunction - functional form passed to `SNESMonitorSet()` to monitor convergence of nonlinear solver
4171bf388a1fSBarry Smith 
4172bf388a1fSBarry Smith      Synopsis:
4173aaa7dc30SBarry Smith      #include <petscsnes.h>
417437fdd005SBarry Smith     PetscErrorCode SNESMonitorFunction(SNES snes, PetscInt its, PetscReal norm, void *mctx)
4175bf388a1fSBarry Smith 
4176c3339decSBarry Smith      Collective
41771843f636SBarry Smith 
41781843f636SBarry Smith     Input Parameters:
4179f6dfbefdSBarry Smith +    snes - the `SNES` context
4180bf388a1fSBarry Smith .    its - iteration number
4181bf388a1fSBarry Smith .    norm - 2-norm function value (may be estimated)
4182bf388a1fSBarry Smith -    mctx - [optional] monitoring context
4183bf388a1fSBarry Smith 
4184878cb397SSatish Balay    Level: advanced
4185878cb397SSatish Balay 
41861cc06b55SBarry Smith .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSet()`, `SNESMonitorGet()`
4187bf388a1fSBarry Smith M*/
4188bf388a1fSBarry Smith 
41899b94acceSBarry Smith /*@C
4190a6570f20SBarry Smith   SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every
4191*0b4b7b1cSBarry Smith   iteration of the `SNES` nonlinear solver to display the iteration's
41929b94acceSBarry Smith   progress.
41939b94acceSBarry Smith 
4194c3339decSBarry Smith   Logically Collective
4195fee21e36SBarry Smith 
4196c7afd0dbSLois Curfman McInnes   Input Parameters:
4197f6dfbefdSBarry Smith + snes           - the `SNES` context
419820f4b53cSBarry Smith . f              - the monitor function,  for the calling sequence see `SNESMonitorFunction`
4199420bcc1bSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
4200dc4c0fb0SBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
42019b94acceSBarry Smith 
42029665c990SLois Curfman McInnes   Options Database Keys:
4203f6dfbefdSBarry Smith + -snes_monitor               - sets `SNESMonitorDefault()`
4204798534f6SMatthew G. Knepley . -snes_monitor draw::draw_lg - sets line graph monitor,
4205dc4c0fb0SBarry 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
4206c7afd0dbSLois Curfman McInnes                                 the options database.
42079665c990SLois Curfman McInnes 
4208dc4c0fb0SBarry Smith   Level: intermediate
4209dc4c0fb0SBarry Smith 
4210f6dfbefdSBarry Smith   Note:
42116bc08f3fSLois Curfman McInnes   Several different monitoring routines may be set by calling
4212f6dfbefdSBarry Smith   `SNESMonitorSet()` multiple times; all will be called in the
42136bc08f3fSLois Curfman McInnes   order in which they were set.
4214639f9d9dSBarry Smith 
4215420bcc1bSBarry Smith   Fortran Note:
4216f6dfbefdSBarry Smith   Only a single monitor function can be set for each `SNES` object
4217025f1a04SBarry Smith 
42181cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESMonitorDefault()`, `SNESMonitorCancel()`, `SNESMonitorFunction`
42199b94acceSBarry Smith @*/
4220d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorSet(SNES snes, PetscErrorCode (*f)(SNES, PetscInt, PetscReal, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
4221d71ae5a4SJacob Faibussowitsch {
4222b90d0a6eSBarry Smith   PetscInt  i;
422378064530SBarry Smith   PetscBool identical;
4224b90d0a6eSBarry Smith 
42253a40ed3dSBarry Smith   PetscFunctionBegin;
42260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4227b90d0a6eSBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
42289566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))snes->monitor[i], snes->monitorcontext[i], snes->monitordestroy[i], &identical));
42293ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4230649052a6SBarry Smith   }
42315f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numbermonitors < MAXSNESMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
42326e4dcb14SBarry Smith   snes->monitor[snes->numbermonitors]          = f;
4233b8a78c4aSBarry Smith   snes->monitordestroy[snes->numbermonitors]   = monitordestroy;
4234639f9d9dSBarry Smith   snes->monitorcontext[snes->numbermonitors++] = (void *)mctx;
42353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42369b94acceSBarry Smith }
42379b94acceSBarry Smith 
4238a278d85bSSatish Balay /*@
4239f6dfbefdSBarry Smith   SNESMonitorCancel - Clears all the monitor functions for a `SNES` object.
42405cd90555SBarry Smith 
4241c3339decSBarry Smith   Logically Collective
4242c7afd0dbSLois Curfman McInnes 
42432fe279fdSBarry Smith   Input Parameter:
4244f6dfbefdSBarry Smith . snes - the `SNES` context
42455cd90555SBarry Smith 
42461a480d89SAdministrator   Options Database Key:
4247a6570f20SBarry Smith . -snes_monitor_cancel - cancels all monitors that have been hardwired
4248dc4c0fb0SBarry Smith                          into a code by calls to `SNESMonitorSet()`, but does not cancel those
4249c7afd0dbSLois Curfman McInnes                          set via the options database
42505cd90555SBarry Smith 
4251dc4c0fb0SBarry Smith   Level: intermediate
4252dc4c0fb0SBarry Smith 
4253f6dfbefdSBarry Smith   Note:
4254f6dfbefdSBarry Smith   There is no way to clear one specific monitor from a `SNES` object.
42555cd90555SBarry Smith 
42561cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESMonitorGet()`, `SNESMonitorDefault()`, `SNESMonitorSet()`
42575cd90555SBarry Smith @*/
4258d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESMonitorCancel(SNES snes)
4259d71ae5a4SJacob Faibussowitsch {
4260d952e501SBarry Smith   PetscInt i;
4261d952e501SBarry Smith 
42625cd90555SBarry Smith   PetscFunctionBegin;
42630700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4264d952e501SBarry Smith   for (i = 0; i < snes->numbermonitors; i++) {
426548a46eb9SPierre Jolivet     if (snes->monitordestroy[i]) PetscCall((*snes->monitordestroy[i])(&snes->monitorcontext[i]));
4266d952e501SBarry Smith   }
42675cd90555SBarry Smith   snes->numbermonitors = 0;
42683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42695cd90555SBarry Smith }
42705cd90555SBarry Smith 
4271bf388a1fSBarry Smith /*MC
4272bf388a1fSBarry Smith     SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver
4273bf388a1fSBarry Smith 
4274bf388a1fSBarry Smith      Synopsis:
4275aaa7dc30SBarry Smith      #include <petscsnes.h>
427637fdd005SBarry Smith      PetscErrorCode SNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *cctx)
4277bf388a1fSBarry Smith 
4278c3339decSBarry Smith      Collective
42791843f636SBarry Smith 
42801843f636SBarry Smith     Input Parameters:
4281f6dfbefdSBarry Smith +    snes - the `SNES` context
4282bf388a1fSBarry Smith .    it - current iteration (0 is the first and is before any Newton step)
4283bf388a1fSBarry Smith .    xnorm - 2-norm of current iterate
4284bf388a1fSBarry Smith .    gnorm - 2-norm of current step
42851843f636SBarry Smith .    f - 2-norm of function
42861843f636SBarry Smith -    cctx - [optional] convergence context
42871843f636SBarry Smith 
42881843f636SBarry Smith     Output Parameter:
42891843f636SBarry Smith .    reason - reason for convergence/divergence, only needs to be set when convergence or divergence is detected
4290bf388a1fSBarry Smith 
4291878cb397SSatish Balay    Level: intermediate
4292bf388a1fSBarry Smith 
42931cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve`, `SNESSetConvergenceTest()`, `SNESGetConvergenceTest()`
4294bf388a1fSBarry Smith M*/
4295bf388a1fSBarry Smith 
42969b94acceSBarry Smith /*@C
42979b94acceSBarry Smith   SNESSetConvergenceTest - Sets the function that is to be used
42989b94acceSBarry Smith   to test for convergence of the nonlinear iterative solution.
42999b94acceSBarry Smith 
4300c3339decSBarry Smith   Logically Collective
4301fee21e36SBarry Smith 
4302c7afd0dbSLois Curfman McInnes   Input Parameters:
4303f6dfbefdSBarry Smith + snes                        - the `SNES` context
4304e4094ef1SJacob Faibussowitsch . SNESConvergenceTestFunction - routine to test for convergence
4305dc4c0fb0SBarry Smith . cctx                        - [optional] context for private data for the convergence routine  (may be `NULL`)
4306dc4c0fb0SBarry Smith - destroy                     - [optional] destructor for the context (may be `NULL`; `PETSC_NULL_FUNCTION` in Fortran)
43079b94acceSBarry Smith 
430836851e7fSLois Curfman McInnes   Level: advanced
430936851e7fSLois Curfman McInnes 
43101cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedDefault()`, `SNESConvergedSkip()`, `SNESConvergenceTestFunction`
43119b94acceSBarry Smith @*/
4312d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceTest(SNES snes, PetscErrorCode (*SNESConvergenceTestFunction)(SNES, PetscInt, PetscReal, PetscReal, PetscReal, SNESConvergedReason *, void *), void *cctx, PetscErrorCode (*destroy)(void *))
4313d71ae5a4SJacob Faibussowitsch {
43143a40ed3dSBarry Smith   PetscFunctionBegin;
43150700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4316e2a6519dSDmitry Karpeev   if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip;
43171baa6e33SBarry Smith   if (snes->ops->convergeddestroy) PetscCall((*snes->ops->convergeddestroy)(snes->cnvP));
4318bf388a1fSBarry Smith   snes->ops->converged        = SNESConvergenceTestFunction;
43197f7931b9SBarry Smith   snes->ops->convergeddestroy = destroy;
432085385478SLisandro Dalcin   snes->cnvP                  = cctx;
43213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43229b94acceSBarry Smith }
43239b94acceSBarry Smith 
432452baeb72SSatish Balay /*@
4325*0b4b7b1cSBarry Smith   SNESGetConvergedReason - Gets the reason the `SNES` iteration was stopped, which may be due to convergence, divergence, or stagnation
4326184914b5SBarry Smith 
4327184914b5SBarry Smith   Not Collective
4328184914b5SBarry Smith 
4329184914b5SBarry Smith   Input Parameter:
4330f6dfbefdSBarry Smith . snes - the `SNES` context
4331184914b5SBarry Smith 
4332184914b5SBarry Smith   Output Parameter:
4333f6dfbefdSBarry Smith . reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` for the individual convergence tests for complete lists
4334184914b5SBarry Smith 
4335f6dfbefdSBarry Smith   Options Database Key:
43366a4d7782SBarry Smith . -snes_converged_reason - prints the reason to standard out
43376a4d7782SBarry Smith 
4338184914b5SBarry Smith   Level: intermediate
4339184914b5SBarry Smith 
4340f6dfbefdSBarry Smith   Note:
4341f6dfbefdSBarry Smith   Should only be called after the call the `SNESSolve()` is complete, if it is called earlier it returns the value `SNES__CONVERGED_ITERATING`.
4342184914b5SBarry Smith 
43431cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESSetConvergedReason()`, `SNESConvergedReason`, `SNESGetConvergedReasonString()`
4344184914b5SBarry Smith @*/
4345d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReason(SNES snes, SNESConvergedReason *reason)
4346d71ae5a4SJacob Faibussowitsch {
4347184914b5SBarry Smith   PetscFunctionBegin;
43480700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43494f572ea9SToby Isaac   PetscAssertPointer(reason, 2);
4350184914b5SBarry Smith   *reason = snes->reason;
43513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4352184914b5SBarry Smith }
4353184914b5SBarry Smith 
4354c4421ceaSFande Kong /*@C
4355f6dfbefdSBarry Smith   SNESGetConvergedReasonString - Return a human readable string for `SNESConvergedReason`
4356c4421ceaSFande Kong 
4357c4421ceaSFande Kong   Not Collective
4358c4421ceaSFande Kong 
4359c4421ceaSFande Kong   Input Parameter:
4360f6dfbefdSBarry Smith . snes - the `SNES` context
4361c4421ceaSFande Kong 
4362c4421ceaSFande Kong   Output Parameter:
4363dc4c0fb0SBarry Smith . strreason - a human readable string that describes `SNES` converged reason
4364c4421ceaSFande Kong 
436599c90e12SSatish Balay   Level: beginner
4366c4421ceaSFande Kong 
43671cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetConvergedReason()`
4368c4421ceaSFande Kong @*/
4369d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergedReasonString(SNES snes, const char **strreason)
4370d71ae5a4SJacob Faibussowitsch {
4371c4421ceaSFande Kong   PetscFunctionBegin;
4372c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43734f572ea9SToby Isaac   PetscAssertPointer(strreason, 2);
4374c4421ceaSFande Kong   *strreason = SNESConvergedReasons[snes->reason];
43753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4376c4421ceaSFande Kong }
4377c4421ceaSFande Kong 
437833866048SMatthew G. Knepley /*@
4379f6dfbefdSBarry Smith   SNESSetConvergedReason - Sets the reason the `SNES` iteration was stopped.
438033866048SMatthew G. Knepley 
438133866048SMatthew G. Knepley   Not Collective
438233866048SMatthew G. Knepley 
438333866048SMatthew G. Knepley   Input Parameters:
4384f6dfbefdSBarry Smith + snes   - the `SNES` context
4385f6dfbefdSBarry Smith - reason - negative value indicates diverged, positive value converged, see `SNESConvergedReason` or the
438633866048SMatthew G. Knepley             manual pages for the individual convergence tests for complete lists
438733866048SMatthew G. Knepley 
4388f6dfbefdSBarry Smith   Level: developer
4389f6dfbefdSBarry Smith 
4390420bcc1bSBarry Smith   Developer Note:
4391f6dfbefdSBarry Smith   Called inside the various `SNESSolve()` implementations
439233866048SMatthew G. Knepley 
43931cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetConvergedReason()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
439433866048SMatthew G. Knepley @*/
4395d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergedReason(SNES snes, SNESConvergedReason reason)
4396d71ae5a4SJacob Faibussowitsch {
439733866048SMatthew G. Knepley   PetscFunctionBegin;
439833866048SMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
43995f3c5e7aSBarry Smith   PetscCheck(!snes->errorifnotconverged || reason > 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_PLIB, "SNES code should have previously errored due to negative reason");
440033866048SMatthew G. Knepley   snes->reason = reason;
44013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
440233866048SMatthew G. Knepley }
440333866048SMatthew G. Knepley 
4404c9005455SLois Curfman McInnes /*@
4405420bcc1bSBarry Smith   SNESSetConvergenceHistory - Sets the arrays used to hold the convergence history.
4406c9005455SLois Curfman McInnes 
4407c3339decSBarry Smith   Logically Collective
4408fee21e36SBarry Smith 
4409c7afd0dbSLois Curfman McInnes   Input Parameters:
4410f6dfbefdSBarry Smith + snes  - iterative context obtained from `SNESCreate()`
44118c7482ecSBarry Smith . a     - array to hold history, this array will contain the function norms computed at each step
4412cd5578b5SBarry Smith . its   - integer array holds the number of linear iterations for each solve.
4413420bcc1bSBarry Smith . na    - size of `a` and `its`
4414f6dfbefdSBarry Smith - reset - `PETSC_TRUE` indicates each new nonlinear solve resets the history counter to zero,
4415758f92a0SBarry Smith           else it continues storing new values for new nonlinear solves after the old ones
4416c7afd0dbSLois Curfman McInnes 
4417dc4c0fb0SBarry Smith   Level: intermediate
4418dc4c0fb0SBarry Smith 
4419308dcc3eSBarry Smith   Notes:
442077e5a1f9SBarry Smith   If 'a' and 'its' are `NULL` then space is allocated for the history. If 'na' is `PETSC_DECIDE` then a
442177e5a1f9SBarry Smith   default array of length 1,000 is allocated.
4422308dcc3eSBarry Smith 
4423c9005455SLois Curfman McInnes   This routine is useful, e.g., when running a code for purposes
4424c9005455SLois Curfman McInnes   of accurate performance monitoring, when no I/O should be done
4425c9005455SLois Curfman McInnes   during the section of code that is being timed.
4426c9005455SLois Curfman McInnes 
4427420bcc1bSBarry Smith   If the arrays run out of space after a number of iterations then the later values are not saved in the history
4428420bcc1bSBarry Smith 
44291cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetConvergenceHistory()`
4430c9005455SLois Curfman McInnes @*/
4431d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetConvergenceHistory(SNES snes, PetscReal a[], PetscInt its[], PetscInt na, PetscBool reset)
4432d71ae5a4SJacob Faibussowitsch {
44333a40ed3dSBarry Smith   PetscFunctionBegin;
44340700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
44354f572ea9SToby Isaac   if (a) PetscAssertPointer(a, 2);
44364f572ea9SToby Isaac   if (its) PetscAssertPointer(its, 3);
44377a1ec6d4SBarry Smith   if (!a) {
443877e5a1f9SBarry Smith     if (na == PETSC_DECIDE) na = 1000;
44399566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(na, &a, na, &its));
4440071fcb05SBarry Smith     snes->conv_hist_alloc = PETSC_TRUE;
4441308dcc3eSBarry Smith   }
4442c9005455SLois Curfman McInnes   snes->conv_hist       = a;
4443758f92a0SBarry Smith   snes->conv_hist_its   = its;
4444115dd874SBarry Smith   snes->conv_hist_max   = (size_t)na;
4445a12bc48fSLisandro Dalcin   snes->conv_hist_len   = 0;
4446758f92a0SBarry Smith   snes->conv_hist_reset = reset;
44473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4448758f92a0SBarry Smith }
4449758f92a0SBarry Smith 
4450d1e78c4fSBarry Smith #if defined(PETSC_HAVE_MATLAB)
4451c6db04a5SJed Brown   #include <engine.h> /* MATLAB include file */
4452c6db04a5SJed Brown   #include <mex.h>    /* MATLAB include file */
445399e0435eSBarry Smith 
4454d71ae5a4SJacob Faibussowitsch PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes)
4455d71ae5a4SJacob Faibussowitsch {
4456308dcc3eSBarry Smith   mxArray   *mat;
4457308dcc3eSBarry Smith   PetscInt   i;
4458308dcc3eSBarry Smith   PetscReal *ar;
4459308dcc3eSBarry Smith 
4460308dcc3eSBarry Smith   mat = mxCreateDoubleMatrix(snes->conv_hist_len, 1, mxREAL);
4461308dcc3eSBarry Smith   ar  = (PetscReal *)mxGetData(mat);
4462f5af7f23SKarl Rupp   for (i = 0; i < snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i];
446311cc89d2SBarry Smith   return mat;
4464308dcc3eSBarry Smith }
4465308dcc3eSBarry Smith #endif
4466308dcc3eSBarry Smith 
44670c4c9dddSBarry Smith /*@C
4468420bcc1bSBarry Smith   SNESGetConvergenceHistory - Gets the arrays used to hold the convergence history.
4469758f92a0SBarry Smith 
44703f9fe445SBarry Smith   Not Collective
4471758f92a0SBarry Smith 
4472758f92a0SBarry Smith   Input Parameter:
4473f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
4474758f92a0SBarry Smith 
4475758f92a0SBarry Smith   Output Parameters:
4476f6dfbefdSBarry Smith + a   - array to hold history, usually was set with `SNESSetConvergenceHistory()`
4477758f92a0SBarry Smith . its - integer array holds the number of linear iterations (or
4478758f92a0SBarry Smith          negative if not converged) for each solve.
447920f4b53cSBarry Smith - na  - size of `a` and `its`
4480758f92a0SBarry Smith 
4481dc4c0fb0SBarry Smith   Level: intermediate
4482dc4c0fb0SBarry Smith 
448320f4b53cSBarry Smith   Note:
448420f4b53cSBarry Smith   This routine is useful, e.g., when running a code for purposes
448520f4b53cSBarry Smith   of accurate performance monitoring, when no I/O should be done
448620f4b53cSBarry Smith   during the section of code that is being timed.
448720f4b53cSBarry Smith 
4488420bcc1bSBarry Smith   Fortran Note:
4489758f92a0SBarry Smith   The calling sequence for this routine in Fortran is
4490dc4c0fb0SBarry Smith .vb
4491dc4c0fb0SBarry Smith     call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr)
4492dc4c0fb0SBarry Smith .ve
4493758f92a0SBarry Smith 
44941cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceHistory()`
4495758f92a0SBarry Smith @*/
4496d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetConvergenceHistory(SNES snes, PetscReal *a[], PetscInt *its[], PetscInt *na)
4497d71ae5a4SJacob Faibussowitsch {
4498758f92a0SBarry Smith   PetscFunctionBegin;
44990700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4500758f92a0SBarry Smith   if (a) *a = snes->conv_hist;
4501758f92a0SBarry Smith   if (its) *its = snes->conv_hist_its;
4502115dd874SBarry Smith   if (na) *na = (PetscInt)snes->conv_hist_len;
45033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4504c9005455SLois Curfman McInnes }
4505c9005455SLois Curfman McInnes 
4506ac226902SBarry Smith /*@C
450776b2cf59SMatthew Knepley   SNESSetUpdate - Sets the general-purpose update function called
4508eec8f646SJed Brown   at the beginning of every iteration of the nonlinear solve. Specifically
450953e5d35bSStefano Zampini   it is called just before the Jacobian is "evaluated" and after the function
451053e5d35bSStefano Zampini   evaluation.
451176b2cf59SMatthew Knepley 
4512c3339decSBarry Smith   Logically Collective
451376b2cf59SMatthew Knepley 
451476b2cf59SMatthew Knepley   Input Parameters:
4515a2b725a8SWilliam Gropp + snes - The nonlinear solver context
451653e5d35bSStefano Zampini - func - The update function; for calling sequence see `SNESUpdateFn`
451776b2cf59SMatthew Knepley 
4518fe97e370SBarry Smith   Level: advanced
4519fe97e370SBarry Smith 
4520420bcc1bSBarry Smith   Notes:
4521f6dfbefdSBarry 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
4522f6dfbefdSBarry Smith   to `SNESSetFunction()`, or `SNESSetPicard()`
452353e5d35bSStefano Zampini   This is not used by most users, and it is intended to provide a general hook that is run
452453e5d35bSStefano Zampini   right before the direction step is computed.
452553e5d35bSStefano Zampini   Users are free to modify the current residual vector,
452653e5d35bSStefano Zampini   the current linearization point, or any other vector associated to the specific solver used.
452753e5d35bSStefano Zampini   If such modifications take place, it is the user responsibility to update all the relevant
452853e5d35bSStefano Zampini   vectors.
452976b2cf59SMatthew Knepley 
4530aaa8cc7dSPierre 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.
45316b7fb656SBarry Smith 
4532e4094ef1SJacob Faibussowitsch .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetJacobian()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchSetPostCheck()`, `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRSetPostCheck()`,
453353e5d35bSStefano Zampini          `SNESMonitorSet()`
453476b2cf59SMatthew Knepley @*/
453553e5d35bSStefano Zampini PetscErrorCode SNESSetUpdate(SNES snes, SNESUpdateFn *func)
4536d71ae5a4SJacob Faibussowitsch {
453776b2cf59SMatthew Knepley   PetscFunctionBegin;
45380700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4539e7788613SBarry Smith   snes->ops->update = func;
45403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
454176b2cf59SMatthew Knepley }
454276b2cf59SMatthew Knepley 
4543ffeef943SBarry Smith /*@
4544f6dfbefdSBarry Smith   SNESConvergedReasonView - Displays the reason a `SNES` solve converged or diverged to a viewer
45452a359c20SBarry Smith 
4546c3339decSBarry Smith   Collective
45472a359c20SBarry Smith 
4548e4094ef1SJacob Faibussowitsch   Input Parameters:
4549f6dfbefdSBarry Smith + snes   - iterative context obtained from `SNESCreate()`
45502a359c20SBarry Smith - viewer - the viewer to display the reason
45512a359c20SBarry Smith 
45522a359c20SBarry Smith   Options Database Keys:
4553ee300463SSatish Balay + -snes_converged_reason          - print reason for converged or diverged, also prints number of iterations
4554ee300463SSatish Balay - -snes_converged_reason ::failed - only print reason and number of iterations when diverged
4555eafd5ff0SAlex Lindsay 
4556420bcc1bSBarry Smith   Level: beginner
4557420bcc1bSBarry Smith 
4558f6dfbefdSBarry Smith   Note:
4559f6dfbefdSBarry Smith   To change the format of the output call `PetscViewerPushFormat`(viewer,format) before this call. Use `PETSC_VIEWER_DEFAULT` for the default,
4560f6dfbefdSBarry Smith   use `PETSC_VIEWER_FAILED` to only display a reason if it fails.
45612a359c20SBarry Smith 
45621cc06b55SBarry Smith .seealso: [](ch_snes), `SNESConvergedReason`, `PetscViewer`, `SNES`,
4563f6dfbefdSBarry Smith           `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`, `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`,
4564f6dfbefdSBarry Smith           `SNESConvergedReasonViewFromOptions()`,
4565db781477SPatrick Sanan           `PetscViewerPushFormat()`, `PetscViewerPopFormat()`
45662a359c20SBarry Smith @*/
4567d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonView(SNES snes, PetscViewer viewer)
4568d71ae5a4SJacob Faibussowitsch {
456975cca76cSMatthew G. Knepley   PetscViewerFormat format;
45702a359c20SBarry Smith   PetscBool         isAscii;
45712a359c20SBarry Smith 
45722a359c20SBarry Smith   PetscFunctionBegin;
457319a666eeSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
45749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isAscii));
45752a359c20SBarry Smith   if (isAscii) {
45769566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
457765bf60d2SBarry Smith     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel + 1));
457875cca76cSMatthew G. Knepley     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
457975cca76cSMatthew G. Knepley       DM       dm;
458075cca76cSMatthew G. Knepley       Vec      u;
458175cca76cSMatthew G. Knepley       PetscDS  prob;
458275cca76cSMatthew G. Knepley       PetscInt Nf, f;
458395cbbfd3SMatthew G. Knepley       PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
458495cbbfd3SMatthew G. Knepley       void    **exactCtx;
458575cca76cSMatthew G. Knepley       PetscReal error;
458675cca76cSMatthew G. Knepley 
45879566063dSJacob Faibussowitsch       PetscCall(SNESGetDM(snes, &dm));
45889566063dSJacob Faibussowitsch       PetscCall(SNESGetSolution(snes, &u));
45899566063dSJacob Faibussowitsch       PetscCall(DMGetDS(dm, &prob));
45909566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(prob, &Nf));
45919566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(Nf, &exactSol, Nf, &exactCtx));
45929566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]));
45939566063dSJacob Faibussowitsch       PetscCall(DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error));
45949566063dSJacob Faibussowitsch       PetscCall(PetscFree2(exactSol, exactCtx));
45959566063dSJacob Faibussowitsch       if (error < 1.0e-11) PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n"));
459663a3b9bcSJacob Faibussowitsch       else PetscCall(PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", (double)error));
459775cca76cSMatthew G. Knepley     }
4598eafd5ff0SAlex Lindsay     if (snes->reason > 0 && format != PETSC_VIEWER_FAILED) {
45992a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
460063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear %s solve converged due to %s iterations %" PetscInt_FMT "\n", ((PetscObject)snes)->prefix, SNESConvergedReasons[snes->reason], snes->iter));
46012a359c20SBarry Smith       } else {
460263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve converged due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46032a359c20SBarry Smith       }
4604eafd5ff0SAlex Lindsay     } else if (snes->reason <= 0) {
46052a359c20SBarry Smith       if (((PetscObject)snes)->prefix) {
460663a3b9bcSJacob 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));
46072a359c20SBarry Smith       } else {
460863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Nonlinear solve did not converge due to %s iterations %" PetscInt_FMT "\n", SNESConvergedReasons[snes->reason], snes->iter));
46092a359c20SBarry Smith       }
46102a359c20SBarry Smith     }
461165bf60d2SBarry Smith     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel + 1));
46122a359c20SBarry Smith   }
46133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46142a359c20SBarry Smith }
46152a359c20SBarry Smith 
4616c4421ceaSFande Kong /*@C
4617c4421ceaSFande Kong   SNESConvergedReasonViewSet - Sets an ADDITIONAL function that is to be used at the
4618aaa8cc7dSPierre Jolivet   end of the nonlinear solver to display the convergence reason of the nonlinear solver.
4619c4421ceaSFande Kong 
4620c3339decSBarry Smith   Logically Collective
4621c4421ceaSFande Kong 
4622c4421ceaSFande Kong   Input Parameters:
4623f6dfbefdSBarry Smith + snes              - the `SNES` context
4624420bcc1bSBarry Smith . f                 - the `SNESConvergedReason` view function
4625420bcc1bSBarry Smith . vctx              - [optional] user-defined context for private data for the `SNESConvergedReason` view function (use `NULL` if no context is desired)
4626420bcc1bSBarry Smith - reasonviewdestroy - [optional] routine that frees the context (may be `NULL`)
4627420bcc1bSBarry Smith 
4628420bcc1bSBarry Smith   Calling sequence of `f`:
4629420bcc1bSBarry Smith + snes - the `SNES` context
4630420bcc1bSBarry Smith - vctx - [optional] user-defined context for private data for the function
4631420bcc1bSBarry Smith 
4632420bcc1bSBarry Smith   Calling sequence of `reasonviewerdestroy`:
4633420bcc1bSBarry Smith . vctx - [optional] user-defined context for private data for the function
4634c4421ceaSFande Kong 
4635c4421ceaSFande Kong   Options Database Keys:
4636f6dfbefdSBarry Smith + -snes_converged_reason             - sets a default `SNESConvergedReasonView()`
4637420bcc1bSBarry Smith - -snes_converged_reason_view_cancel - cancels all converged reason viewers that have been hardwired into a code by
4638420bcc1bSBarry Smith                                        calls to `SNESConvergedReasonViewSet()`, but does not cancel those set via the options database.
4639c4421ceaSFande Kong 
4640dc4c0fb0SBarry Smith   Level: intermediate
4641dc4c0fb0SBarry Smith 
4642f6dfbefdSBarry Smith   Note:
4643c4421ceaSFande Kong   Several different converged reason view routines may be set by calling
4644f6dfbefdSBarry Smith   `SNESConvergedReasonViewSet()` multiple times; all will be called in the
4645c4421ceaSFande Kong   order in which they were set.
4646c4421ceaSFande Kong 
46471cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedReason`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`, `SNESConvergedReasonViewCancel()`
4648c4421ceaSFande Kong @*/
4649420bcc1bSBarry Smith PetscErrorCode SNESConvergedReasonViewSet(SNES snes, PetscErrorCode (*f)(SNES snes, void *vctx), void *vctx, PetscErrorCode (*reasonviewdestroy)(void **vctx))
4650d71ae5a4SJacob Faibussowitsch {
4651c4421ceaSFande Kong   PetscInt  i;
4652c4421ceaSFande Kong   PetscBool identical;
4653c4421ceaSFande Kong 
4654c4421ceaSFande Kong   PetscFunctionBegin;
4655c4421ceaSFande Kong   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4656c4421ceaSFande Kong   for (i = 0; i < snes->numberreasonviews; i++) {
46579566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, vctx, reasonviewdestroy, (PetscErrorCode (*)(void))snes->reasonview[i], snes->reasonviewcontext[i], snes->reasonviewdestroy[i], &identical));
46583ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
4659c4421ceaSFande Kong   }
46605f80ce2aSJacob Faibussowitsch   PetscCheck(snes->numberreasonviews < MAXSNESREASONVIEWS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many SNES reasonview set");
4661c4421ceaSFande Kong   snes->reasonview[snes->numberreasonviews]          = f;
4662c4421ceaSFande Kong   snes->reasonviewdestroy[snes->numberreasonviews]   = reasonviewdestroy;
4663c4421ceaSFande Kong   snes->reasonviewcontext[snes->numberreasonviews++] = (void *)vctx;
46643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4665c4421ceaSFande Kong }
4666c4421ceaSFande Kong 
466791f3e32bSBarry Smith /*@
4668420bcc1bSBarry Smith   SNESConvergedReasonViewFromOptions - Processes command line options to determine if/how a `SNESConvergedReason` is to be viewed at the end of `SNESSolve()`
4669*0b4b7b1cSBarry Smith   All the user-provided viewer routines set with `SNESConvergedReasonViewSet()` will be called, if they exist.
46702a359c20SBarry Smith 
4671c3339decSBarry Smith   Collective
46722a359c20SBarry Smith 
46732fe279fdSBarry Smith   Input Parameter:
4674f6dfbefdSBarry Smith . snes - the `SNES` object
46752a359c20SBarry Smith 
4676f6dfbefdSBarry Smith   Level: advanced
46772a359c20SBarry Smith 
46781cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESConvergedReason`, `SNESConvergedReasonViewSet()`, `SNESCreate()`, `SNESSetUp()`, `SNESDestroy()`,
4679f6dfbefdSBarry Smith           `SNESSetTolerances()`, `SNESConvergedDefault()`, `SNESGetConvergedReason()`, `SNESConvergedReasonView()`
46802a359c20SBarry Smith @*/
4681d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESConvergedReasonViewFromOptions(SNES snes)
4682d71ae5a4SJacob Faibussowitsch {
46832a359c20SBarry Smith   static PetscBool incall = PETSC_FALSE;
46842a359c20SBarry Smith 
46852a359c20SBarry Smith   PetscFunctionBegin;
46863ba16761SJacob Faibussowitsch   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
46872a359c20SBarry Smith   incall = PETSC_TRUE;
4688c4421ceaSFande Kong 
4689c4421ceaSFande Kong   /* All user-provided viewers are called first, if they exist. */
469036d43d94SBarry Smith   for (PetscInt i = 0; i < snes->numberreasonviews; i++) PetscCall((*snes->reasonview[i])(snes, snes->reasonviewcontext[i]));
4691c4421ceaSFande Kong 
4692c4421ceaSFande Kong   /* Call PETSc default routine if users ask for it */
469336d43d94SBarry Smith   if (snes->convergedreasonviewer) {
469436d43d94SBarry Smith     PetscCall(PetscViewerPushFormat(snes->convergedreasonviewer, snes->convergedreasonformat));
469536d43d94SBarry Smith     PetscCall(SNESConvergedReasonView(snes, snes->convergedreasonviewer));
469636d43d94SBarry Smith     PetscCall(PetscViewerPopFormat(snes->convergedreasonviewer));
46972a359c20SBarry Smith   }
46982a359c20SBarry Smith   incall = PETSC_FALSE;
46993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47002a359c20SBarry Smith }
47012a359c20SBarry Smith 
4702487a658cSBarry Smith /*@
4703*0b4b7b1cSBarry Smith   SNESSolve - Solves a nonlinear system $F(x) = b $ associated with a `SNES` object
47049b94acceSBarry Smith 
4705c3339decSBarry Smith   Collective
4706c7afd0dbSLois Curfman McInnes 
4707b2002411SLois Curfman McInnes   Input Parameters:
4708f6dfbefdSBarry Smith + snes - the `SNES` context
4709*0b4b7b1cSBarry Smith . b    - the constant part of the equation $F(x) = b$, or `NULL` to use zero.
471085385478SLisandro Dalcin - x    - the solution vector.
47119b94acceSBarry Smith 
4712dc4c0fb0SBarry Smith   Level: beginner
4713dc4c0fb0SBarry Smith 
4714f6dfbefdSBarry Smith   Note:
4715420bcc1bSBarry Smith   The user should initialize the vector, `x`, with the initial guess
4716420bcc1bSBarry Smith   for the nonlinear solve prior to calling `SNESSolve()` or use `SNESSetInitialSolution()`.  In particular,
47178ddd3da0SLois Curfman McInnes   to employ an initial guess of zero, the user should explicitly set
4718*0b4b7b1cSBarry Smith   `x` to zero by calling `VecSet()`.
47198ddd3da0SLois Curfman McInnes 
47201cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESCreate()`, `SNESDestroy()`, `SNESSetFunction()`, `SNESSetJacobian()`, `SNESSetGridSequence()`, `SNESGetSolution()`,
4721db781477SPatrick Sanan           `SNESNewtonTRSetPreCheck()`, `SNESNewtonTRGetPreCheck()`, `SNESNewtonTRSetPostCheck()`, `SNESNewtonTRGetPostCheck()`,
4722420bcc1bSBarry Smith           `SNESLineSearchSetPostCheck()`, `SNESLineSearchGetPostCheck()`, `SNESLineSearchSetPreCheck()`, `SNESLineSearchGetPreCheck()`, `SNESSetInitialSolution()`
47239b94acceSBarry Smith @*/
4724d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSolve(SNES snes, Vec b, Vec x)
4725d71ae5a4SJacob Faibussowitsch {
4726ace3abfcSBarry Smith   PetscBool flg;
4727efd51863SBarry Smith   PetscInt  grid;
47280298fd71SBarry Smith   Vec       xcreated = NULL;
4729caa4e7f2SJed Brown   DM        dm;
4730052efed2SBarry Smith 
47313a40ed3dSBarry Smith   PetscFunctionBegin;
47320700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4733a69afd8bSBarry Smith   if (x) PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4734a69afd8bSBarry Smith   if (x) PetscCheckSameComm(snes, 1, x, 3);
47350700a824SBarry Smith   if (b) PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
473685385478SLisandro Dalcin   if (b) PetscCheckSameComm(snes, 1, b, 2);
473785385478SLisandro Dalcin 
473834b4d3a8SMatthew G. Knepley   /* High level operations using the nonlinear solver */
473906fc46c8SMatthew G. Knepley   {
474006fc46c8SMatthew G. Knepley     PetscViewer       viewer;
474106fc46c8SMatthew G. Knepley     PetscViewerFormat format;
47427c88af5aSMatthew G. Knepley     PetscInt          num;
474306fc46c8SMatthew G. Knepley     PetscBool         flg;
474406fc46c8SMatthew G. Knepley     static PetscBool  incall = PETSC_FALSE;
474506fc46c8SMatthew G. Knepley 
474606fc46c8SMatthew G. Knepley     if (!incall) {
474734b4d3a8SMatthew G. Knepley       /* Estimate the convergence rate of the discretization */
4748648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg));
474906fc46c8SMatthew G. Knepley       if (flg) {
475006fc46c8SMatthew G. Knepley         PetscConvEst conv;
475146079b62SMatthew G. Knepley         DM           dm;
475246079b62SMatthew G. Knepley         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
475346079b62SMatthew G. Knepley         PetscInt     Nf;
475406fc46c8SMatthew G. Knepley 
475506fc46c8SMatthew G. Knepley         incall = PETSC_TRUE;
47569566063dSJacob Faibussowitsch         PetscCall(SNESGetDM(snes, &dm));
47579566063dSJacob Faibussowitsch         PetscCall(DMGetNumFields(dm, &Nf));
47589566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(Nf, &alpha));
47599566063dSJacob Faibussowitsch         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)snes), &conv));
47609566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)snes));
47619566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetFromOptions(conv));
47629566063dSJacob Faibussowitsch         PetscCall(PetscConvEstSetUp(conv));
47639566063dSJacob Faibussowitsch         PetscCall(PetscConvEstGetConvRate(conv, alpha));
47649566063dSJacob Faibussowitsch         PetscCall(PetscViewerPushFormat(viewer, format));
47659566063dSJacob Faibussowitsch         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
47669566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4767648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
47689566063dSJacob Faibussowitsch         PetscCall(PetscConvEstDestroy(&conv));
47699566063dSJacob Faibussowitsch         PetscCall(PetscFree(alpha));
477006fc46c8SMatthew G. Knepley         incall = PETSC_FALSE;
477106fc46c8SMatthew G. Knepley       }
477234b4d3a8SMatthew G. Knepley       /* Adaptively refine the initial grid */
4773b2588ea6SMatthew G. Knepley       num = 1;
47749566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_initial", &num, &flg));
477534b4d3a8SMatthew G. Knepley       if (flg) {
477634b4d3a8SMatthew G. Knepley         DMAdaptor adaptor;
477734b4d3a8SMatthew G. Knepley 
477834b4d3a8SMatthew G. Knepley         incall = PETSC_TRUE;
47799566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
47809566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
47819566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
47829566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
47839566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
47849566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x));
47859566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
478634b4d3a8SMatthew G. Knepley         incall = PETSC_FALSE;
478734b4d3a8SMatthew G. Knepley       }
47887c88af5aSMatthew G. Knepley       /* Use grid sequencing to adapt */
47897c88af5aSMatthew G. Knepley       num = 0;
47909566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)snes)->prefix, "-snes_adapt_sequence", &num, NULL));
47917c88af5aSMatthew G. Knepley       if (num) {
47927c88af5aSMatthew G. Knepley         DMAdaptor   adaptor;
4793e03fd340SMatthew G. Knepley         const char *prefix;
47947c88af5aSMatthew G. Knepley 
47957c88af5aSMatthew G. Knepley         incall = PETSC_TRUE;
47969566063dSJacob Faibussowitsch         PetscCall(DMAdaptorCreate(PetscObjectComm((PetscObject)snes), &adaptor));
4797e03fd340SMatthew G. Knepley         PetscCall(SNESGetOptionsPrefix(snes, &prefix));
4798e03fd340SMatthew G. Knepley         PetscCall(DMAdaptorSetOptionsPrefix(adaptor, prefix));
47999566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSolver(adaptor, snes));
48009566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetSequenceLength(adaptor, num));
48019566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetFromOptions(adaptor));
48029566063dSJacob Faibussowitsch         PetscCall(DMAdaptorSetUp(adaptor));
4803e5148a0bSMatthew G. Knepley         PetscCall(PetscObjectViewFromOptions((PetscObject)adaptor, NULL, "-snes_adapt_view"));
48049566063dSJacob Faibussowitsch         PetscCall(DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x));
48059566063dSJacob Faibussowitsch         PetscCall(DMAdaptorDestroy(&adaptor));
48067c88af5aSMatthew G. Knepley         incall = PETSC_FALSE;
48077c88af5aSMatthew G. Knepley       }
480806fc46c8SMatthew G. Knepley     }
480906fc46c8SMatthew G. Knepley   }
4810ad540459SPierre Jolivet   if (!x) x = snes->vec_sol;
4811caa4e7f2SJed Brown   if (!x) {
48129566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
48139566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(dm, &xcreated));
4814a69afd8bSBarry Smith     x = xcreated;
4815a69afd8bSBarry Smith   }
48169566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view_pre"));
4817f05ece33SBarry Smith 
48189566063dSJacob Faibussowitsch   for (grid = 0; grid < snes->gridsequence; grid++) PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4819efd51863SBarry Smith   for (grid = 0; grid < snes->gridsequence + 1; grid++) {
482085385478SLisandro Dalcin     /* set solution vector */
48219566063dSJacob Faibussowitsch     if (!grid) PetscCall(PetscObjectReference((PetscObject)x));
48229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_sol));
482385385478SLisandro Dalcin     snes->vec_sol = x;
48249566063dSJacob Faibussowitsch     PetscCall(SNESGetDM(snes, &dm));
4825caa4e7f2SJed Brown 
4826caa4e7f2SJed Brown     /* set affine vector if provided */
48279566063dSJacob Faibussowitsch     if (b) PetscCall(PetscObjectReference((PetscObject)b));
48289566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&snes->vec_rhs));
482985385478SLisandro Dalcin     snes->vec_rhs = b;
483085385478SLisandro Dalcin 
48315f80ce2aSJacob 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");
48325f80ce2aSJacob Faibussowitsch     PetscCheck(snes->vec_func != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be function vector");
4833dd8e379bSPierre Jolivet     PetscCheck(snes->vec_rhs != snes->vec_sol, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "Solution vector cannot be right-hand side vector");
4834aa624791SPierre Jolivet     if (!snes->vec_sol_update /* && snes->vec_sol */) PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_sol_update));
48359566063dSJacob Faibussowitsch     PetscCall(DMShellSetGlobalVector(dm, snes->vec_sol));
48369566063dSJacob Faibussowitsch     PetscCall(SNESSetUp(snes));
48373f149594SLisandro Dalcin 
48387eee914bSBarry Smith     if (!grid) {
48399927e4dfSBarry Smith       if (snes->ops->computeinitialguess) PetscCallBack("SNES callback compute initial guess", (*snes->ops->computeinitialguess)(snes, snes->vec_sol, snes->initialguessP));
4840dd568438SSatish Balay     }
4841d25893d9SBarry Smith 
4842abc0a331SBarry Smith     if (snes->conv_hist_reset) snes->conv_hist_len = 0;
484312b1dd1aSStefano Zampini     PetscCall(SNESResetCounters(snes));
48442d157150SStefano Zampini     snes->reason = SNES_CONVERGED_ITERATING;
48459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(SNES_Solve, snes, 0, 0, 0));
4846dbbe0bcdSBarry Smith     PetscUseTypeMethod(snes, solve);
48479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(SNES_Solve, snes, 0, 0, 0));
48482d157150SStefano Zampini     PetscCheck(snes->reason, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Internal error, solver %s returned without setting converged reason", ((PetscObject)snes)->type_name);
4849422a814eSBarry Smith     snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */
48503f149594SLisandro Dalcin 
485137ec4e1aSPeter Brune     if (snes->lagjac_persist) snes->jac_iter += snes->iter;
485237ec4e1aSPeter Brune     if (snes->lagpre_persist) snes->pre_iter += snes->iter;
485337ec4e1aSPeter Brune 
4854648c30bcSBarry Smith     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)snes), ((PetscObject)snes)->options, ((PetscObject)snes)->prefix, "-snes_test_local_min", NULL, NULL, &flg));
48559566063dSJacob Faibussowitsch     if (flg && !PetscPreLoadingOn) PetscCall(SNESTestLocalMin(snes));
4856c4421ceaSFande Kong     /* Call converged reason views. This may involve user-provided viewers as well */
48579566063dSJacob Faibussowitsch     PetscCall(SNESConvergedReasonViewFromOptions(snes));
48585968eb51SBarry Smith 
48595f80ce2aSJacob Faibussowitsch     if (snes->errorifnotconverged) PetscCheck(snes->reason >= 0, PetscObjectComm((PetscObject)snes), PETSC_ERR_NOT_CONVERGED, "SNESSolve has not converged");
48609c8e83a9SBarry Smith     if (snes->reason < 0) break;
4861efd51863SBarry Smith     if (grid < snes->gridsequence) {
4862efd51863SBarry Smith       DM  fine;
4863efd51863SBarry Smith       Vec xnew;
4864efd51863SBarry Smith       Mat interp;
4865efd51863SBarry Smith 
48669566063dSJacob Faibussowitsch       PetscCall(DMRefine(snes->dm, PetscObjectComm((PetscObject)snes), &fine));
48675f80ce2aSJacob Faibussowitsch       PetscCheck(fine, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_INCOMP, "DMRefine() did not perform any refinement, cannot continue grid sequencing");
48689566063dSJacob Faibussowitsch       PetscCall(DMCreateInterpolation(snes->dm, fine, &interp, NULL));
48699566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(fine, &xnew));
48709566063dSJacob Faibussowitsch       PetscCall(MatInterpolate(interp, x, xnew));
48719566063dSJacob Faibussowitsch       PetscCall(DMInterpolate(snes->dm, interp, fine));
48729566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&interp));
4873efd51863SBarry Smith       x = xnew;
4874efd51863SBarry Smith 
48759566063dSJacob Faibussowitsch       PetscCall(SNESReset(snes));
48769566063dSJacob Faibussowitsch       PetscCall(SNESSetDM(snes, fine));
48779566063dSJacob Faibussowitsch       PetscCall(SNESResetFromOptions(snes));
48789566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fine));
48799566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes))));
4880efd51863SBarry Smith     }
4881efd51863SBarry Smith   }
48829566063dSJacob Faibussowitsch   PetscCall(SNESViewFromOptions(snes, NULL, "-snes_view"));
48839566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(snes->vec_sol, (PetscObject)snes, "-snes_view_solution"));
48849566063dSJacob Faibussowitsch   PetscCall(DMMonitor(snes->dm));
48859566063dSJacob Faibussowitsch   PetscCall(SNESMonitorPauseFinal_Internal(snes));
48863f7e2da0SPeter Brune 
48879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xcreated));
48889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsBlock((PetscObject)snes));
48893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48909b94acceSBarry Smith }
48919b94acceSBarry Smith 
48929b94acceSBarry Smith /* --------- Internal routines for SNES Package --------- */
48939b94acceSBarry Smith 
4894cc4c1da9SBarry Smith /*@
4895*0b4b7b1cSBarry Smith   SNESSetType - Sets the algorithm/method to be used to solve the nonlinear system with the given `SNES`
48969b94acceSBarry Smith 
4897c3339decSBarry Smith   Collective
4898fee21e36SBarry Smith 
4899c7afd0dbSLois Curfman McInnes   Input Parameters:
4900f6dfbefdSBarry Smith + snes - the `SNES` context
4901454a90a3SBarry Smith - type - a known method
4902c7afd0dbSLois Curfman McInnes 
4903c7afd0dbSLois Curfman McInnes   Options Database Key:
4904454a90a3SBarry Smith . -snes_type <type> - Sets the method; use -help for a list
490504d7464bSBarry Smith    of available methods (for instance, newtonls or newtontr)
4906ae12b187SLois Curfman McInnes 
4907dc4c0fb0SBarry Smith   Level: intermediate
4908dc4c0fb0SBarry Smith 
49099b94acceSBarry Smith   Notes:
4910*0b4b7b1cSBarry Smith   See `SNESType` for available methods (for instance)
4911f6dfbefdSBarry Smith +    `SNESNEWTONLS` - Newton's method with line search
4912c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49134a221d59SStefano Zampini -    `SNESNEWTONTR` - Newton's method with trust region
4914c7afd0dbSLois Curfman McInnes   (systems of nonlinear equations)
49159b94acceSBarry Smith 
4916f6dfbefdSBarry Smith   Normally, it is best to use the `SNESSetFromOptions()` command and then
4917f6dfbefdSBarry Smith   set the `SNES` solver type from the options database rather than by using
4918ae12b187SLois Curfman McInnes   this routine.  Using the options database provides the user with
4919ae12b187SLois Curfman McInnes   maximum flexibility in evaluating the many nonlinear solvers.
4920f6dfbefdSBarry Smith   The `SNESSetType()` routine is provided for those situations where it
4921ae12b187SLois Curfman McInnes   is necessary to set the nonlinear solver independently of the command
4922ae12b187SLois Curfman McInnes   line or options database.  This might be the case, for example, when
4923ae12b187SLois Curfman McInnes   the choice of solver changes during the execution of the program,
4924ae12b187SLois Curfman McInnes   and the user's application is taking responsibility for choosing the
4925b0a32e0cSBarry Smith   appropriate method.
492636851e7fSLois Curfman McInnes 
4927420bcc1bSBarry Smith   Developer Note:
4928f6dfbefdSBarry Smith   `SNESRegister()` adds a constructor for a new `SNESType` to `SNESList`, `SNESSetType()` locates
4929f6dfbefdSBarry Smith   the constructor in that list and calls it to create the specific object.
49308f6c3df8SBarry Smith 
49311cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESType`, `SNESCreate()`, `SNESDestroy()`, `SNESGetType()`, `SNESSetFromOptions()`
49329b94acceSBarry Smith @*/
4933d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetType(SNES snes, SNESType type)
4934d71ae5a4SJacob Faibussowitsch {
4935ace3abfcSBarry Smith   PetscBool match;
49365f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(SNES);
49373a40ed3dSBarry Smith 
49383a40ed3dSBarry Smith   PetscFunctionBegin;
49390700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49404f572ea9SToby Isaac   PetscAssertPointer(type, 2);
494182bf6240SBarry Smith 
49429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)snes, type, &match));
49433ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
494492ff6ae8SBarry Smith 
49459566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(SNESList, type, &r));
49466adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested SNES type %s", type);
494775396ef9SLisandro Dalcin   /* Destroy the previous private SNES context */
4948dbbe0bcdSBarry Smith   PetscTryTypeMethod(snes, destroy);
494975396ef9SLisandro Dalcin   /* Reinitialize function pointers in SNESOps structure */
49509e5d0892SLisandro Dalcin   snes->ops->setup          = NULL;
49519e5d0892SLisandro Dalcin   snes->ops->solve          = NULL;
49529e5d0892SLisandro Dalcin   snes->ops->view           = NULL;
49539e5d0892SLisandro Dalcin   snes->ops->setfromoptions = NULL;
49549e5d0892SLisandro Dalcin   snes->ops->destroy        = NULL;
49557fe760d5SStefano Zampini 
49567fe760d5SStefano Zampini   /* It may happen the user has customized the line search before calling SNESSetType */
49579566063dSJacob Faibussowitsch   if (((PetscObject)snes)->type_name) PetscCall(SNESLineSearchDestroy(&snes->linesearch));
49587fe760d5SStefano Zampini 
495975396ef9SLisandro Dalcin   /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */
496075396ef9SLisandro Dalcin   snes->setupcalled = PETSC_FALSE;
4961f5af7f23SKarl Rupp 
49629566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)snes, type));
49639566063dSJacob Faibussowitsch   PetscCall((*r)(snes));
49643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49659b94acceSBarry Smith }
49669b94acceSBarry Smith 
4967cc4c1da9SBarry Smith /*@
4968f6dfbefdSBarry Smith   SNESGetType - Gets the `SNES` method type and name (as a string).
49699b94acceSBarry Smith 
4970c7afd0dbSLois Curfman McInnes   Not Collective
4971c7afd0dbSLois Curfman McInnes 
49729b94acceSBarry Smith   Input Parameter:
49734b0e389bSBarry Smith . snes - nonlinear solver context
49749b94acceSBarry Smith 
49759b94acceSBarry Smith   Output Parameter:
4976f6dfbefdSBarry Smith . type - `SNES` method (a character string)
49779b94acceSBarry Smith 
497836851e7fSLois Curfman McInnes   Level: intermediate
497936851e7fSLois Curfman McInnes 
49801cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetType()`, `SNESType`, `SNESSetFromOptions()`, `SNES`
49819b94acceSBarry Smith @*/
4982d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetType(SNES snes, SNESType *type)
4983d71ae5a4SJacob Faibussowitsch {
49843a40ed3dSBarry Smith   PetscFunctionBegin;
49850700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
49864f572ea9SToby Isaac   PetscAssertPointer(type, 2);
49877adad957SLisandro Dalcin   *type = ((PetscObject)snes)->type_name;
49883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49899b94acceSBarry Smith }
49909b94acceSBarry Smith 
49913cd8a7caSMatthew G. Knepley /*@
4992f6dfbefdSBarry Smith   SNESSetSolution - Sets the solution vector for use by the `SNES` routines.
49933cd8a7caSMatthew G. Knepley 
4994c3339decSBarry Smith   Logically Collective
49953cd8a7caSMatthew G. Knepley 
49963cd8a7caSMatthew G. Knepley   Input Parameters:
4997f6dfbefdSBarry Smith + snes - the `SNES` context obtained from `SNESCreate()`
49983cd8a7caSMatthew G. Knepley - u    - the solution vector
49993cd8a7caSMatthew G. Knepley 
50003cd8a7caSMatthew G. Knepley   Level: beginner
50013cd8a7caSMatthew G. Knepley 
50021cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESGetSolution()`, `Vec`
50033cd8a7caSMatthew G. Knepley @*/
5004d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetSolution(SNES snes, Vec u)
5005d71ae5a4SJacob Faibussowitsch {
50063cd8a7caSMatthew G. Knepley   DM dm;
50073cd8a7caSMatthew G. Knepley 
50083cd8a7caSMatthew G. Knepley   PetscFunctionBegin;
50093cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50103cd8a7caSMatthew G. Knepley   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
50119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)u));
50129566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&snes->vec_sol));
50133cd8a7caSMatthew G. Knepley 
50143cd8a7caSMatthew G. Knepley   snes->vec_sol = u;
50153cd8a7caSMatthew G. Knepley 
50169566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
50179566063dSJacob Faibussowitsch   PetscCall(DMShellSetGlobalVector(dm, u));
50183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50193cd8a7caSMatthew G. Knepley }
50203cd8a7caSMatthew G. Knepley 
502152baeb72SSatish Balay /*@
50229b94acceSBarry Smith   SNESGetSolution - Returns the vector where the approximate solution is
5023f6dfbefdSBarry Smith   stored. This is the fine grid solution when using `SNESSetGridSequence()`.
50249b94acceSBarry Smith 
5025420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5026c7afd0dbSLois Curfman McInnes 
50279b94acceSBarry Smith   Input Parameter:
5028f6dfbefdSBarry Smith . snes - the `SNES` context
50299b94acceSBarry Smith 
50309b94acceSBarry Smith   Output Parameter:
50319b94acceSBarry Smith . x - the solution
50329b94acceSBarry Smith 
503370e92668SMatthew Knepley   Level: intermediate
503436851e7fSLois Curfman McInnes 
50351cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetSolution()`, `SNESSolve()`, `SNES`, `SNESGetSolutionUpdate()`, `SNESGetFunction()`
50369b94acceSBarry Smith @*/
5037d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolution(SNES snes, Vec *x)
5038d71ae5a4SJacob Faibussowitsch {
50393a40ed3dSBarry Smith   PetscFunctionBegin;
50400700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50414f572ea9SToby Isaac   PetscAssertPointer(x, 2);
504285385478SLisandro Dalcin   *x = snes->vec_sol;
50433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
504470e92668SMatthew Knepley }
504570e92668SMatthew Knepley 
504652baeb72SSatish Balay /*@
50479b94acceSBarry Smith   SNESGetSolutionUpdate - Returns the vector where the solution update is
50489b94acceSBarry Smith   stored.
50499b94acceSBarry Smith 
5050420bcc1bSBarry Smith   Not Collective, but `x` is parallel if `snes` is parallel
5051c7afd0dbSLois Curfman McInnes 
50529b94acceSBarry Smith   Input Parameter:
5053f6dfbefdSBarry Smith . snes - the `SNES` context
50549b94acceSBarry Smith 
50559b94acceSBarry Smith   Output Parameter:
50569b94acceSBarry Smith . x - the solution update
50579b94acceSBarry Smith 
505836851e7fSLois Curfman McInnes   Level: advanced
505936851e7fSLois Curfman McInnes 
50601cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESGetSolution()`, `SNESGetFunction()`
50619b94acceSBarry Smith @*/
5062d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetSolutionUpdate(SNES snes, Vec *x)
5063d71ae5a4SJacob Faibussowitsch {
50643a40ed3dSBarry Smith   PetscFunctionBegin;
50650700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
50664f572ea9SToby Isaac   PetscAssertPointer(x, 2);
506785385478SLisandro Dalcin   *x = snes->vec_sol_update;
50683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50699b94acceSBarry Smith }
50709b94acceSBarry Smith 
50719b94acceSBarry Smith /*@C
5072f6dfbefdSBarry Smith   SNESGetFunction - Returns the function that defines the nonlinear system set with `SNESSetFunction()`
50739b94acceSBarry Smith 
5074420bcc1bSBarry Smith   Not Collective, but `r` is parallel if `snes` is parallel. Collective if `r` is requested, but has not been created yet.
5075c7afd0dbSLois Curfman McInnes 
50769b94acceSBarry Smith   Input Parameter:
5077f6dfbefdSBarry Smith . snes - the `SNES` context
50789b94acceSBarry Smith 
5079d8d19677SJose E. Roman   Output Parameters:
5080dc4c0fb0SBarry Smith + r   - the vector that is used to store residuals (or `NULL` if you don't want it)
50818434afd1SBarry Smith . f   - the function (or `NULL` if you don't want it);  for calling sequence see `SNESFunctionFn`
5082dc4c0fb0SBarry Smith - ctx - the function context (or `NULL` if you don't want it)
50839b94acceSBarry Smith 
508436851e7fSLois Curfman McInnes   Level: advanced
508536851e7fSLois Curfman McInnes 
5086f6dfbefdSBarry Smith   Note:
5087dc4c0fb0SBarry Smith   The vector `r` DOES NOT, in general, contain the current value of the `SNES` nonlinear function
508804edfde5SBarry Smith 
50898434afd1SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetFunction()`, `SNESGetSolution()`, `SNESFunctionFn`
50909b94acceSBarry Smith @*/
50918434afd1SBarry Smith PetscErrorCode SNESGetFunction(SNES snes, Vec *r, SNESFunctionFn **f, void **ctx)
5092d71ae5a4SJacob Faibussowitsch {
50936cab3a1bSJed Brown   DM dm;
5094a63bb30eSJed Brown 
50953a40ed3dSBarry Smith   PetscFunctionBegin;
50960700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5097a63bb30eSJed Brown   if (r) {
5098a63bb30eSJed Brown     if (!snes->vec_func) {
5099a63bb30eSJed Brown       if (snes->vec_rhs) {
51009566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_rhs, &snes->vec_func));
5101a63bb30eSJed Brown       } else if (snes->vec_sol) {
51029566063dSJacob Faibussowitsch         PetscCall(VecDuplicate(snes->vec_sol, &snes->vec_func));
5103a63bb30eSJed Brown       } else if (snes->dm) {
51049566063dSJacob Faibussowitsch         PetscCall(DMCreateGlobalVector(snes->dm, &snes->vec_func));
5105a63bb30eSJed Brown       }
5106a63bb30eSJed Brown     }
5107a63bb30eSJed Brown     *r = snes->vec_func;
5108a63bb30eSJed Brown   }
51099566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51109566063dSJacob Faibussowitsch   PetscCall(DMSNESGetFunction(dm, f, ctx));
51113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51129b94acceSBarry Smith }
51139b94acceSBarry Smith 
5114c79ef259SPeter Brune /*@C
511537fdd005SBarry Smith   SNESGetNGS - Returns the function and context set with `SNESSetNGS()`
5116c79ef259SPeter Brune 
5117c79ef259SPeter Brune   Input Parameter:
5118f6dfbefdSBarry Smith . snes - the `SNES` context
5119c79ef259SPeter Brune 
5120d8d19677SJose E. Roman   Output Parameters:
51218434afd1SBarry Smith + f   - the function (or `NULL`) see `SNESNGSFn` for calling sequence
5122dc4c0fb0SBarry Smith - ctx - the function context (or `NULL`)
5123c79ef259SPeter Brune 
5124c79ef259SPeter Brune   Level: advanced
5125c79ef259SPeter Brune 
51268434afd1SBarry Smith .seealso: [](ch_snes), `SNESSetNGS()`, `SNESGetFunction()`, `SNESNGSFn`
5127c79ef259SPeter Brune @*/
51288434afd1SBarry Smith PetscErrorCode SNESGetNGS(SNES snes, SNESNGSFn **f, void **ctx)
5129d71ae5a4SJacob Faibussowitsch {
51306cab3a1bSJed Brown   DM dm;
51316cab3a1bSJed Brown 
5132646217ecSPeter Brune   PetscFunctionBegin;
5133646217ecSPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51349566063dSJacob Faibussowitsch   PetscCall(SNESGetDM(snes, &dm));
51359566063dSJacob Faibussowitsch   PetscCall(DMSNESGetNGS(dm, f, ctx));
51363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5137646217ecSPeter Brune }
5138646217ecSPeter Brune 
5139cc4c1da9SBarry Smith /*@
51403c7409f5SSatish Balay   SNESSetOptionsPrefix - Sets the prefix used for searching for all
5141f6dfbefdSBarry Smith   `SNES` options in the database.
51423c7409f5SSatish Balay 
5143c3339decSBarry Smith   Logically Collective
5144fee21e36SBarry Smith 
5145d8d19677SJose E. Roman   Input Parameters:
5146f6dfbefdSBarry Smith + snes   - the `SNES` context
5147c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5148c7afd0dbSLois Curfman McInnes 
5149dc4c0fb0SBarry Smith   Level: advanced
5150dc4c0fb0SBarry Smith 
5151f6dfbefdSBarry Smith   Note:
5152a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5153c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5154d850072dSLois Curfman McInnes 
51551cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetFromOptions()`, `SNESAppendOptionsPrefix()`
51563c7409f5SSatish Balay @*/
5157d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetOptionsPrefix(SNES snes, const char prefix[])
5158d71ae5a4SJacob Faibussowitsch {
51593a40ed3dSBarry Smith   PetscFunctionBegin;
51600700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51619566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes, prefix));
51629566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
516335f5d045SPeter Brune   if (snes->linesearch) {
51649566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51659566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch, prefix));
516635f5d045SPeter Brune   }
51679566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(snes->ksp, prefix));
51683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51693c7409f5SSatish Balay }
51703c7409f5SSatish Balay 
5171cc4c1da9SBarry Smith /*@
5172f525115eSLois Curfman McInnes   SNESAppendOptionsPrefix - Appends to the prefix used for searching for all
5173f6dfbefdSBarry Smith   `SNES` options in the database.
51743c7409f5SSatish Balay 
5175c3339decSBarry Smith   Logically Collective
5176fee21e36SBarry Smith 
5177c7afd0dbSLois Curfman McInnes   Input Parameters:
5178f6dfbefdSBarry Smith + snes   - the `SNES` context
5179c7afd0dbSLois Curfman McInnes - prefix - the prefix to prepend to all option names
5180c7afd0dbSLois Curfman McInnes 
5181dc4c0fb0SBarry Smith   Level: advanced
5182dc4c0fb0SBarry Smith 
5183f6dfbefdSBarry Smith   Note:
5184a83b1b31SSatish Balay   A hyphen (-) must NOT be given at the beginning of the prefix name.
5185c7afd0dbSLois Curfman McInnes   The first character of all runtime options is AUTOMATICALLY the hyphen.
5186d850072dSLois Curfman McInnes 
51871cc06b55SBarry Smith .seealso: [](ch_snes), `SNESGetOptionsPrefix()`, `SNESSetOptionsPrefix()`
51883c7409f5SSatish Balay @*/
5189d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESAppendOptionsPrefix(SNES snes, const char prefix[])
5190d71ae5a4SJacob Faibussowitsch {
51913a40ed3dSBarry Smith   PetscFunctionBegin;
51920700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
51939566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes, prefix));
51949566063dSJacob Faibussowitsch   if (!snes->ksp) PetscCall(SNESGetKSP(snes, &snes->ksp));
519535f5d045SPeter Brune   if (snes->linesearch) {
51969566063dSJacob Faibussowitsch     PetscCall(SNESGetLineSearch(snes, &snes->linesearch));
51979566063dSJacob Faibussowitsch     PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch, prefix));
519835f5d045SPeter Brune   }
51999566063dSJacob Faibussowitsch   PetscCall(KSPAppendOptionsPrefix(snes->ksp, prefix));
52003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52013c7409f5SSatish Balay }
52023c7409f5SSatish Balay 
5203cc4c1da9SBarry Smith /*@
5204f6dfbefdSBarry Smith   SNESGetOptionsPrefix - Gets the prefix used for searching for all
5205f6dfbefdSBarry Smith   `SNES` options in the database.
52063c7409f5SSatish Balay 
5207c7afd0dbSLois Curfman McInnes   Not Collective
5208c7afd0dbSLois Curfman McInnes 
52093c7409f5SSatish Balay   Input Parameter:
5210f6dfbefdSBarry Smith . snes - the `SNES` context
52113c7409f5SSatish Balay 
52123c7409f5SSatish Balay   Output Parameter:
52133c7409f5SSatish Balay . prefix - pointer to the prefix string used
52143c7409f5SSatish Balay 
521536851e7fSLois Curfman McInnes   Level: advanced
521636851e7fSLois Curfman McInnes 
5217420bcc1bSBarry Smith   Fortran Note:
5218dc4c0fb0SBarry Smith   The user should pass in a string 'prefix' of
5219dc4c0fb0SBarry Smith   sufficient length to hold the prefix.
5220dc4c0fb0SBarry Smith 
52211cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetOptionsPrefix()`, `SNESAppendOptionsPrefix()`
52223c7409f5SSatish Balay @*/
5223d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetOptionsPrefix(SNES snes, const char *prefix[])
5224d71ae5a4SJacob Faibussowitsch {
52253a40ed3dSBarry Smith   PetscFunctionBegin;
52260700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
52279566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)snes, prefix));
52283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52293c7409f5SSatish Balay }
52303c7409f5SSatish Balay 
52313cea93caSBarry Smith /*@C
52321c84c290SBarry Smith   SNESRegister - Adds a method to the nonlinear solver package.
52331c84c290SBarry Smith 
523420f4b53cSBarry Smith   Not Collective
52351c84c290SBarry Smith 
52361c84c290SBarry Smith   Input Parameters:
523720f4b53cSBarry Smith + sname    - name of a new user-defined solver
523820f4b53cSBarry Smith - function - routine to create method context
52391c84c290SBarry Smith 
5240dc4c0fb0SBarry Smith   Level: advanced
5241dc4c0fb0SBarry Smith 
5242f6dfbefdSBarry Smith   Note:
5243f6dfbefdSBarry Smith   `SNESRegister()` may be called multiple times to add several user-defined solvers.
52441c84c290SBarry Smith 
5245e4094ef1SJacob Faibussowitsch   Example Usage:
52461c84c290SBarry Smith .vb
5247bdf89e91SBarry Smith    SNESRegister("my_solver", MySolverCreate);
52481c84c290SBarry Smith .ve
52491c84c290SBarry Smith 
52501c84c290SBarry Smith   Then, your solver can be chosen with the procedural interface via
52511c84c290SBarry Smith $     SNESSetType(snes, "my_solver")
52521c84c290SBarry Smith   or at runtime via the option
52531c84c290SBarry Smith $     -snes_type my_solver
52541c84c290SBarry Smith 
52551cc06b55SBarry Smith .seealso: [](ch_snes), `SNESRegisterAll()`, `SNESRegisterDestroy()`
52563cea93caSBarry Smith @*/
5257d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESRegister(const char sname[], PetscErrorCode (*function)(SNES))
5258d71ae5a4SJacob Faibussowitsch {
5259b2002411SLois Curfman McInnes   PetscFunctionBegin;
52609566063dSJacob Faibussowitsch   PetscCall(SNESInitializePackage());
52619566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&SNESList, sname, function));
52623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5263b2002411SLois Curfman McInnes }
5264da9b6338SBarry Smith 
5265d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESTestLocalMin(SNES snes)
5266d71ae5a4SJacob Faibussowitsch {
526777431f27SBarry Smith   PetscInt    N, i, j;
5268da9b6338SBarry Smith   Vec         u, uh, fh;
5269da9b6338SBarry Smith   PetscScalar value;
5270da9b6338SBarry Smith   PetscReal   norm;
5271da9b6338SBarry Smith 
5272da9b6338SBarry Smith   PetscFunctionBegin;
52739566063dSJacob Faibussowitsch   PetscCall(SNESGetSolution(snes, &u));
52749566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &uh));
52759566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(u, &fh));
5276da9b6338SBarry Smith 
5277da9b6338SBarry Smith   /* currently only works for sequential */
52789566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Testing FormFunction() for local min\n"));
52799566063dSJacob Faibussowitsch   PetscCall(VecGetSize(u, &N));
5280da9b6338SBarry Smith   for (i = 0; i < N; i++) {
52819566063dSJacob Faibussowitsch     PetscCall(VecCopy(u, uh));
528263a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "i = %" PetscInt_FMT "\n", i));
5283da9b6338SBarry Smith     for (j = -10; j < 11; j++) {
52848b49ba18SBarry Smith       value = PetscSign(j) * PetscExpReal(PetscAbs(j) - 10.0);
52859566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
52869566063dSJacob Faibussowitsch       PetscCall(SNESComputeFunction(snes, uh, fh));
52879566063dSJacob Faibussowitsch       PetscCall(VecNorm(fh, NORM_2, &norm));
528863a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "       j norm %" PetscInt_FMT " %18.16e\n", j, (double)norm));
5289da9b6338SBarry Smith       value = -value;
52909566063dSJacob Faibussowitsch       PetscCall(VecSetValue(uh, i, value, ADD_VALUES));
5291da9b6338SBarry Smith     }
5292da9b6338SBarry Smith   }
52939566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&uh));
52949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fh));
52953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5296da9b6338SBarry Smith }
529771f87433Sdalcinl 
529871f87433Sdalcinl /*@
5299f6dfbefdSBarry Smith   SNESKSPSetUseEW - Sets `SNES` to the use Eisenstat-Walker method for
530071f87433Sdalcinl   computing relative tolerance for linear solvers within an inexact
530171f87433Sdalcinl   Newton method.
530271f87433Sdalcinl 
5303c3339decSBarry Smith   Logically Collective
530471f87433Sdalcinl 
530571f87433Sdalcinl   Input Parameters:
5306f6dfbefdSBarry Smith + snes - `SNES` context
5307f6dfbefdSBarry Smith - flag - `PETSC_TRUE` or `PETSC_FALSE`
530871f87433Sdalcinl 
5309f6dfbefdSBarry Smith   Options Database Keys:
531064ba62caSBarry Smith + -snes_ksp_ew                       - use Eisenstat-Walker method for determining linear system convergence
531164ba62caSBarry Smith . -snes_ksp_ew_version ver           - version of  Eisenstat-Walker method
531264ba62caSBarry Smith . -snes_ksp_ew_rtol0 <rtol0>         - Sets rtol0
531364ba62caSBarry Smith . -snes_ksp_ew_rtolmax <rtolmax>     - Sets rtolmax
531464ba62caSBarry Smith . -snes_ksp_ew_gamma <gamma>         - Sets gamma
531564ba62caSBarry Smith . -snes_ksp_ew_alpha <alpha>         - Sets alpha
531664ba62caSBarry Smith . -snes_ksp_ew_alpha2 <alpha2>       - Sets alpha2
531764ba62caSBarry Smith - -snes_ksp_ew_threshold <threshold> - Sets threshold
531864ba62caSBarry Smith 
5319dc4c0fb0SBarry Smith   Level: advanced
5320dc4c0fb0SBarry Smith 
5321f6dfbefdSBarry Smith   Note:
5322f6dfbefdSBarry Smith   The default is to use a constant relative tolerance for
532371f87433Sdalcinl   the inner linear solvers.  Alternatively, one can use the
53241d27aa22SBarry Smith   Eisenstat-Walker method {cite}`ew96`, where the relative convergence tolerance
532571f87433Sdalcinl   is reset at each Newton iteration according progress of the nonlinear
532671f87433Sdalcinl   solver.
532771f87433Sdalcinl 
53281cc06b55SBarry Smith .seealso: [](ch_snes), `KSP`, `SNES`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
532971f87433Sdalcinl @*/
5330d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetUseEW(SNES snes, PetscBool flag)
5331d71ae5a4SJacob Faibussowitsch {
533271f87433Sdalcinl   PetscFunctionBegin;
53330700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5334acfcf0e5SJed Brown   PetscValidLogicalCollectiveBool(snes, flag, 2);
533571f87433Sdalcinl   snes->ksp_ewconv = flag;
53363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
533771f87433Sdalcinl }
533871f87433Sdalcinl 
533971f87433Sdalcinl /*@
5340f6dfbefdSBarry Smith   SNESKSPGetUseEW - Gets if `SNES` is using Eisenstat-Walker method
534171f87433Sdalcinl   for computing relative tolerance for linear solvers within an
534271f87433Sdalcinl   inexact Newton method.
534371f87433Sdalcinl 
534471f87433Sdalcinl   Not Collective
534571f87433Sdalcinl 
534671f87433Sdalcinl   Input Parameter:
5347f6dfbefdSBarry Smith . snes - `SNES` context
534871f87433Sdalcinl 
534971f87433Sdalcinl   Output Parameter:
5350f6dfbefdSBarry Smith . flag - `PETSC_TRUE` or `PETSC_FALSE`
535171f87433Sdalcinl 
535271f87433Sdalcinl   Level: advanced
535371f87433Sdalcinl 
53541cc06b55SBarry Smith .seealso: [](ch_snes), `SNESKSPSetUseEW()`, `SNESKSPGetParametersEW()`, `SNESKSPSetParametersEW()`
535571f87433Sdalcinl @*/
5356d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag)
5357d71ae5a4SJacob Faibussowitsch {
535871f87433Sdalcinl   PetscFunctionBegin;
53590700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
53604f572ea9SToby Isaac   PetscAssertPointer(flag, 2);
536171f87433Sdalcinl   *flag = snes->ksp_ewconv;
53623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536371f87433Sdalcinl }
536471f87433Sdalcinl 
536571f87433Sdalcinl /*@
5366fa9f3622SBarry Smith   SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker
536771f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
536871f87433Sdalcinl   Newton method.
536971f87433Sdalcinl 
5370c3339decSBarry Smith   Logically Collective
537171f87433Sdalcinl 
537271f87433Sdalcinl   Input Parameters:
5373f6dfbefdSBarry Smith + snes      - `SNES` context
53740f0abf79SStefano Zampini . version   - version 1, 2 (default is 2), 3 or 4
537571f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
537671f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
537771f87433Sdalcinl . gamma     - multiplicative factor for version 2 rtol computation
537871f87433Sdalcinl              (0 <= gamma2 <= 1)
537971f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
538071f87433Sdalcinl . alpha2    - power for safeguard
538171f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
538271f87433Sdalcinl 
5383dc4c0fb0SBarry Smith   Level: advanced
5384dc4c0fb0SBarry Smith 
5385f6dfbefdSBarry Smith   Notes:
538671f87433Sdalcinl   Version 3 was contributed by Luis Chacon, June 2006.
538771f87433Sdalcinl 
538877e5a1f9SBarry Smith   Use `PETSC_CURRENT` to retain the default for any of the parameters.
538971f87433Sdalcinl 
53901cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPGetParametersEW()`
539171f87433Sdalcinl @*/
5392d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPSetParametersEW(SNES snes, PetscInt version, PetscReal rtol_0, PetscReal rtol_max, PetscReal gamma, PetscReal alpha, PetscReal alpha2, PetscReal threshold)
5393d71ae5a4SJacob Faibussowitsch {
5394fa9f3622SBarry Smith   SNESKSPEW *kctx;
53955fd66863SKarl Rupp 
539671f87433Sdalcinl   PetscFunctionBegin;
53970700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5398fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
53995f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
5400c5eb9154SBarry Smith   PetscValidLogicalCollectiveInt(snes, version, 2);
5401c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_0, 3);
5402c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, rtol_max, 4);
5403c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, gamma, 5);
5404c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha, 6);
5405c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, alpha2, 7);
5406c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(snes, threshold, 8);
540771f87433Sdalcinl 
540877e5a1f9SBarry Smith   if (version != PETSC_CURRENT) kctx->version = version;
540977e5a1f9SBarry Smith   if (rtol_0 != (PetscReal)PETSC_CURRENT) kctx->rtol_0 = rtol_0;
541077e5a1f9SBarry Smith   if (rtol_max != (PetscReal)PETSC_CURRENT) kctx->rtol_max = rtol_max;
541177e5a1f9SBarry Smith   if (gamma != (PetscReal)PETSC_CURRENT) kctx->gamma = gamma;
541277e5a1f9SBarry Smith   if (alpha != (PetscReal)PETSC_CURRENT) kctx->alpha = alpha;
541377e5a1f9SBarry Smith   if (alpha2 != (PetscReal)PETSC_CURRENT) kctx->alpha2 = alpha2;
541477e5a1f9SBarry Smith   if (threshold != (PetscReal)PETSC_CURRENT) kctx->threshold = threshold;
541571f87433Sdalcinl 
54160f0abf79SStefano 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);
54170b121fc5SBarry 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);
54180b121fc5SBarry 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);
54190b121fc5SBarry 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);
54200b121fc5SBarry 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);
54210b121fc5SBarry 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);
54223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
542371f87433Sdalcinl }
542471f87433Sdalcinl 
542571f87433Sdalcinl /*@
5426fa9f3622SBarry Smith   SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker
542771f87433Sdalcinl   convergence criteria for the linear solvers within an inexact
542871f87433Sdalcinl   Newton method.
542971f87433Sdalcinl 
543071f87433Sdalcinl   Not Collective
543171f87433Sdalcinl 
543297bb3fdcSJose E. Roman   Input Parameter:
5433f6dfbefdSBarry Smith . snes - `SNES` context
543471f87433Sdalcinl 
543571f87433Sdalcinl   Output Parameters:
54360f0abf79SStefano Zampini + version   - version 1, 2 (default is 2), 3 or 4
543771f87433Sdalcinl . rtol_0    - initial relative tolerance (0 <= rtol_0 < 1)
543871f87433Sdalcinl . rtol_max  - maximum relative tolerance (0 <= rtol_max < 1)
5439bf388a1fSBarry Smith . gamma     - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1)
544071f87433Sdalcinl . alpha     - power for version 2 rtol computation (1 < alpha <= 2)
544171f87433Sdalcinl . alpha2    - power for safeguard
544271f87433Sdalcinl - threshold - threshold for imposing safeguard (0 < threshold < 1)
544371f87433Sdalcinl 
544471f87433Sdalcinl   Level: advanced
544571f87433Sdalcinl 
54461cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `SNESKSPSetUseEW()`, `SNESKSPGetUseEW()`, `SNESKSPSetParametersEW()`
544771f87433Sdalcinl @*/
5448d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESKSPGetParametersEW(SNES snes, PetscInt *version, PetscReal *rtol_0, PetscReal *rtol_max, PetscReal *gamma, PetscReal *alpha, PetscReal *alpha2, PetscReal *threshold)
5449d71ae5a4SJacob Faibussowitsch {
5450fa9f3622SBarry Smith   SNESKSPEW *kctx;
54515fd66863SKarl Rupp 
545271f87433Sdalcinl   PetscFunctionBegin;
54530700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5454fa9f3622SBarry Smith   kctx = (SNESKSPEW *)snes->kspconvctx;
54555f80ce2aSJacob Faibussowitsch   PetscCheck(kctx, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "No Eisenstat-Walker context existing");
545671f87433Sdalcinl   if (version) *version = kctx->version;
545771f87433Sdalcinl   if (rtol_0) *rtol_0 = kctx->rtol_0;
545871f87433Sdalcinl   if (rtol_max) *rtol_max = kctx->rtol_max;
545971f87433Sdalcinl   if (gamma) *gamma = kctx->gamma;
546071f87433Sdalcinl   if (alpha) *alpha = kctx->alpha;
546171f87433Sdalcinl   if (alpha2) *alpha2 = kctx->alpha2;
546271f87433Sdalcinl   if (threshold) *threshold = kctx->threshold;
54633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546471f87433Sdalcinl }
546571f87433Sdalcinl 
54665c0db29aSPierre Jolivet PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5467d71ae5a4SJacob Faibussowitsch {
54685c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5469fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
547077e5a1f9SBarry Smith   PetscReal  rtol = PETSC_CURRENT, stol;
547171f87433Sdalcinl 
547271f87433Sdalcinl   PetscFunctionBegin;
54733ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
547430058271SDmitry Karpeev   if (!snes->iter) {
547530058271SDmitry Karpeev     rtol = kctx->rtol_0; /* first time in, so use the original user rtol */
54769566063dSJacob Faibussowitsch     PetscCall(VecNorm(snes->vec_func, NORM_2, &kctx->norm_first));
54770f0abf79SStefano Zampini   } else {
54780fdf79fbSJacob 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);
547971f87433Sdalcinl     if (kctx->version == 1) {
54800f0abf79SStefano Zampini       rtol = PetscAbsReal(snes->norm - kctx->lresid_last) / kctx->norm_last;
548185ec1a3cSBarry Smith       stol = PetscPowReal(kctx->rtol_last, kctx->alpha2);
548271f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
548371f87433Sdalcinl     } else if (kctx->version == 2) {
548485ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
548585ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
548671f87433Sdalcinl       if (stol > kctx->threshold) rtol = PetscMax(rtol, stol);
548771f87433Sdalcinl     } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */
548885ec1a3cSBarry Smith       rtol = kctx->gamma * PetscPowReal(snes->norm / kctx->norm_last, kctx->alpha);
548971f87433Sdalcinl       /* safeguard: avoid sharp decrease of rtol */
549085ec1a3cSBarry Smith       stol = kctx->gamma * PetscPowReal(kctx->rtol_last, kctx->alpha);
549171f87433Sdalcinl       stol = PetscMax(rtol, stol);
549271f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
549371f87433Sdalcinl       /* safeguard: avoid oversolving */
549430058271SDmitry Karpeev       stol = kctx->gamma * (kctx->norm_first * snes->rtol) / snes->norm;
549571f87433Sdalcinl       stol = PetscMax(rtol, stol);
549671f87433Sdalcinl       rtol = PetscMin(kctx->rtol_0, stol);
54970fdf79fbSJacob Faibussowitsch     } else /* if (kctx->version == 4) */ {
54980fdf79fbSJacob Faibussowitsch       /* H.-B. An et al. Journal of Computational and Applied Mathematics 200 (2007) 47-60 */
54990f0abf79SStefano Zampini       PetscReal ared = PetscAbsReal(kctx->norm_last - snes->norm);
55000f0abf79SStefano Zampini       PetscReal pred = PetscAbsReal(kctx->norm_last - kctx->lresid_last);
55010f0abf79SStefano Zampini       PetscReal rk   = ared / pred;
55020f0abf79SStefano Zampini       if (rk < kctx->v4_p1) rtol = 1. - 2. * kctx->v4_p1;
55030f0abf79SStefano Zampini       else if (rk < kctx->v4_p2) rtol = kctx->rtol_last;
55040f0abf79SStefano Zampini       else if (rk < kctx->v4_p3) rtol = kctx->v4_m1 * kctx->rtol_last;
55050f0abf79SStefano Zampini       else rtol = kctx->v4_m2 * kctx->rtol_last;
55060f0abf79SStefano Zampini 
5507a4598233SStefano 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;
55080f0abf79SStefano Zampini       kctx->rtol_last_2 = kctx->rtol_last;
55090f0abf79SStefano Zampini       kctx->rk_last_2   = kctx->rk_last;
55100f0abf79SStefano Zampini       kctx->rk_last     = rk;
55110fdf79fbSJacob Faibussowitsch     }
55120f0abf79SStefano Zampini   }
55130f0abf79SStefano Zampini   /* safeguard: avoid rtol greater than rtol_max */
551471f87433Sdalcinl   rtol = PetscMin(rtol, kctx->rtol_max);
551577e5a1f9SBarry Smith   PetscCall(KSPSetTolerances(ksp, rtol, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT));
551663a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(snes, "iter %" PetscInt_FMT ", Eisenstat-Walker (version %" PetscInt_FMT ") KSP rtol=%g\n", snes->iter, kctx->version, (double)rtol));
55173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
551871f87433Sdalcinl }
551971f87433Sdalcinl 
55205c0db29aSPierre Jolivet PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, void *ctx)
5521d71ae5a4SJacob Faibussowitsch {
55225c0db29aSPierre Jolivet   SNES       snes = (SNES)ctx;
5523fa9f3622SBarry Smith   SNESKSPEW *kctx = (SNESKSPEW *)snes->kspconvctx;
552471f87433Sdalcinl   PCSide     pcside;
552571f87433Sdalcinl   Vec        lres;
552671f87433Sdalcinl 
552771f87433Sdalcinl   PetscFunctionBegin;
55283ba16761SJacob Faibussowitsch   if (!snes->ksp_ewconv) PetscFunctionReturn(PETSC_SUCCESS);
55299566063dSJacob Faibussowitsch   PetscCall(KSPGetTolerances(ksp, &kctx->rtol_last, NULL, NULL, NULL));
553071dbe336SPeter Brune   kctx->norm_last = snes->norm;
55310f0abf79SStefano Zampini   if (kctx->version == 1 || kctx->version == 4) {
55324f00ce20SMatthew G. Knepley     PC        pc;
55330f0abf79SStefano Zampini     PetscBool getRes;
55344f00ce20SMatthew G. Knepley 
55359566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(ksp, &pc));
55360f0abf79SStefano Zampini     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &getRes));
55370f0abf79SStefano Zampini     if (!getRes) {
55380f0abf79SStefano Zampini       KSPNormType normtype;
55390f0abf79SStefano Zampini 
55400f0abf79SStefano Zampini       PetscCall(KSPGetNormType(ksp, &normtype));
55410f0abf79SStefano Zampini       getRes = (PetscBool)(normtype == KSP_NORM_UNPRECONDITIONED);
55420f0abf79SStefano Zampini     }
55439566063dSJacob Faibussowitsch     PetscCall(KSPGetPCSide(ksp, &pcside));
55440f0abf79SStefano Zampini     if (pcside == PC_RIGHT || getRes) { /* KSP residual is true linear residual */
55459566063dSJacob Faibussowitsch       PetscCall(KSPGetResidualNorm(ksp, &kctx->lresid_last));
554671f87433Sdalcinl     } else {
554771f87433Sdalcinl       /* KSP residual is preconditioned residual */
554871f87433Sdalcinl       /* compute true linear residual norm */
55490f0abf79SStefano Zampini       Mat J;
55500f0abf79SStefano Zampini       PetscCall(KSPGetOperators(ksp, &J, NULL));
55519566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(b, &lres));
55520f0abf79SStefano Zampini       PetscCall(MatMult(J, x, lres));
55539566063dSJacob Faibussowitsch       PetscCall(VecAYPX(lres, -1.0, b));
55549566063dSJacob Faibussowitsch       PetscCall(VecNorm(lres, NORM_2, &kctx->lresid_last));
55559566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&lres));
555671f87433Sdalcinl     }
555771f87433Sdalcinl   }
55583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
555971f87433Sdalcinl }
556071f87433Sdalcinl 
5561d4211eb9SBarry Smith /*@
5562f6dfbefdSBarry Smith   SNESGetKSP - Returns the `KSP` context for a `SNES` solver.
5563d4211eb9SBarry Smith 
5564420bcc1bSBarry Smith   Not Collective, but if `snes` is parallel, then `ksp` is parallel
5565d4211eb9SBarry Smith 
5566d4211eb9SBarry Smith   Input Parameter:
5567f6dfbefdSBarry Smith . snes - the `SNES` context
5568d4211eb9SBarry Smith 
5569d4211eb9SBarry Smith   Output Parameter:
5570f6dfbefdSBarry Smith . ksp - the `KSP` context
5571d4211eb9SBarry Smith 
5572dc4c0fb0SBarry Smith   Level: beginner
5573dc4c0fb0SBarry Smith 
5574d4211eb9SBarry Smith   Notes:
5575f6dfbefdSBarry Smith   The user can then directly manipulate the `KSP` context to set various
5576d4211eb9SBarry Smith   options, etc.  Likewise, the user can then extract and manipulate the
5577f6dfbefdSBarry Smith   `PC` contexts as well.
5578f6dfbefdSBarry Smith 
5579*0b4b7b1cSBarry Smith   Some `SNESType`s do not use a `KSP` but a `KSP` is still returned by this function, changes to that `KSP` will have no effect.
5580d4211eb9SBarry Smith 
55811cc06b55SBarry Smith .seealso: [](ch_snes), `SNES`, `KSP`, `PC`, `KSPGetPC()`, `SNESCreate()`, `KSPCreate()`, `SNESSetKSP()`
5582d4211eb9SBarry Smith @*/
5583d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetKSP(SNES snes, KSP *ksp)
5584d71ae5a4SJacob Faibussowitsch {
558571f87433Sdalcinl   PetscFunctionBegin;
5586d4211eb9SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
55874f572ea9SToby Isaac   PetscAssertPointer(ksp, 2);
5588d4211eb9SBarry Smith 
5589d4211eb9SBarry Smith   if (!snes->ksp) {
55909566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PetscObjectComm((PetscObject)snes), &snes->ksp));
55919566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->ksp, (PetscObject)snes, 1));
5592d4211eb9SBarry Smith 
55935c0db29aSPierre Jolivet     PetscCall(KSPSetPreSolve(snes->ksp, KSPPreSolve_SNESEW, snes));
55945c0db29aSPierre Jolivet     PetscCall(KSPSetPostSolve(snes->ksp, KSPPostSolve_SNESEW, snes));
5595a5c2985bSBarry Smith 
55969566063dSJacob Faibussowitsch     PetscCall(KSPMonitorSetFromOptions(snes->ksp, "-snes_monitor_ksp", "snes_preconditioned_residual", snes));
55979566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptions((PetscObject)snes->ksp, ((PetscObject)snes)->options));
5598d4211eb9SBarry Smith   }
5599d4211eb9SBarry Smith   *ksp = snes->ksp;
56003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
560171f87433Sdalcinl }
56026c699258SBarry Smith 
5603af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
56046c699258SBarry Smith /*@
5605*0b4b7b1cSBarry Smith   SNESSetDM - Sets the `DM` that may be used by some `SNES` nonlinear solvers or their underlying preconditioners
56066c699258SBarry Smith 
5607c3339decSBarry Smith   Logically Collective
56086c699258SBarry Smith 
56096c699258SBarry Smith   Input Parameters:
56102a808120SBarry Smith + snes - the nonlinear solver context
5611420bcc1bSBarry Smith - dm   - the `DM`, cannot be `NULL`
5612dc4c0fb0SBarry Smith 
5613dc4c0fb0SBarry Smith   Level: intermediate
56146c699258SBarry Smith 
5615f6dfbefdSBarry Smith   Note:
5616f6dfbefdSBarry Smith   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
5617f6dfbefdSBarry Smith   even when not using interfaces like `DMSNESSetFunction()`.  Use `DMClone()` to get a distinct `DM` when solving different
5618e03a659cSJed Brown   problems using the same function space.
5619e03a659cSJed Brown 
5620420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESGetDM()`, `KSPSetDM()`, `KSPGetDM()`
56216c699258SBarry Smith @*/
5622d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetDM(SNES snes, DM dm)
5623d71ae5a4SJacob Faibussowitsch {
5624345fed2cSBarry Smith   KSP    ksp;
5625942e3340SBarry Smith   DMSNES sdm;
56266c699258SBarry Smith 
56276c699258SBarry Smith   PetscFunctionBegin;
56280700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56292a808120SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
56309566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)dm));
5631942e3340SBarry Smith   if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
563251f4b3c7SToby Isaac     if (snes->dm->dmsnes && !dm->dmsnes) {
56339566063dSJacob Faibussowitsch       PetscCall(DMCopyDMSNES(snes->dm, dm));
56349566063dSJacob Faibussowitsch       PetscCall(DMGetDMSNES(snes->dm, &sdm));
5635f5af7f23SKarl Rupp       if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */
56366cab3a1bSJed Brown     }
56379566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHookRemove(snes->dm, DMCoarsenHook_SNESVecSol, DMRestrictHook_SNESVecSol, snes));
56389566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&snes->dm));
56396cab3a1bSJed Brown   }
56406c699258SBarry Smith   snes->dm     = dm;
5641116d1032SJed Brown   snes->dmAuto = PETSC_FALSE;
5642f5af7f23SKarl Rupp 
56439566063dSJacob Faibussowitsch   PetscCall(SNESGetKSP(snes, &ksp));
56449566063dSJacob Faibussowitsch   PetscCall(KSPSetDM(ksp, dm));
56459566063dSJacob Faibussowitsch   PetscCall(KSPSetDMActive(ksp, PETSC_FALSE));
5646efd4aadfSBarry Smith   if (snes->npc) {
56479566063dSJacob Faibussowitsch     PetscCall(SNESSetDM(snes->npc, snes->dm));
56489566063dSJacob Faibussowitsch     PetscCall(SNESSetNPCSide(snes, snes->npcside));
56492c155ee1SBarry Smith   }
56503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56516c699258SBarry Smith }
56526c699258SBarry Smith 
56536c699258SBarry Smith /*@
5654*0b4b7b1cSBarry Smith   SNESGetDM - Gets the `DM` that may be used by some `SNES` nonlinear solvers/preconditioners
56556c699258SBarry Smith 
5656*0b4b7b1cSBarry Smith   Not Collective but `dm` obtained is parallel on `snes`
56576c699258SBarry Smith 
56586c699258SBarry Smith   Input Parameter:
5659420bcc1bSBarry Smith . snes - the `SNES` context
56606c699258SBarry Smith 
56616c699258SBarry Smith   Output Parameter:
5662420bcc1bSBarry Smith . dm - the `DM`
56636c699258SBarry Smith 
56646c699258SBarry Smith   Level: intermediate
56656c699258SBarry Smith 
5666420bcc1bSBarry Smith .seealso: [](ch_snes), `DM`, `SNES`, `SNESSetDM()`, `KSPSetDM()`, `KSPGetDM()`
56676c699258SBarry Smith @*/
5668d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetDM(SNES snes, DM *dm)
5669d71ae5a4SJacob Faibussowitsch {
56706c699258SBarry Smith   PetscFunctionBegin;
56710700a824SBarry Smith   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
56726cab3a1bSJed Brown   if (!snes->dm) {
56739566063dSJacob Faibussowitsch     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)snes), &snes->dm));
5674116d1032SJed Brown     snes->dmAuto = PETSC_TRUE;
56756cab3a1bSJed Brown   }
56766c699258SBarry Smith   *dm = snes->dm;
56773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56786c699258SBarry Smith }
56790807856dSBarry Smith 
568031823bd8SMatthew G Knepley /*@
5681be95d8f1SBarry Smith   SNESSetNPC - Sets the nonlinear preconditioner to be used.
568231823bd8SMatthew G Knepley 
5683c3339decSBarry Smith   Collective
568431823bd8SMatthew G Knepley 
568531823bd8SMatthew G Knepley   Input Parameters:
5686f6dfbefdSBarry Smith + snes - iterative context obtained from `SNESCreate()`
5687420bcc1bSBarry Smith - npc  - the nonlinear preconditioner object
568831823bd8SMatthew G Knepley 
5689dc4c0fb0SBarry Smith   Level: developer
5690dc4c0fb0SBarry Smith 
569131823bd8SMatthew G Knepley   Notes:
5692f6dfbefdSBarry Smith   Use `SNESGetNPC()` to retrieve the preconditioner context (for example,
569331823bd8SMatthew G Knepley   to configure it using the API).
569431823bd8SMatthew G Knepley 
5695f6dfbefdSBarry Smith   Only some `SNESType` can use a nonlinear preconditioner
5696f6dfbefdSBarry Smith 
5697420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNGS`, `SNESFAS`, `SNESGetNPC()`, `SNESHasNPC()`
569831823bd8SMatthew G Knepley @*/
5699d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPC(SNES snes, SNES npc)
5700d71ae5a4SJacob Faibussowitsch {
570131823bd8SMatthew G Knepley   PetscFunctionBegin;
570231823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5703f6dfbefdSBarry Smith   PetscValidHeaderSpecific(npc, SNES_CLASSID, 2);
5704f6dfbefdSBarry Smith   PetscCheckSameComm(snes, 1, npc, 2);
5705f6dfbefdSBarry Smith   PetscCall(PetscObjectReference((PetscObject)npc));
57069566063dSJacob Faibussowitsch   PetscCall(SNESDestroy(&snes->npc));
5707f6dfbefdSBarry Smith   snes->npc = npc;
57083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
570931823bd8SMatthew G Knepley }
571031823bd8SMatthew G Knepley 
571131823bd8SMatthew G Knepley /*@
5712f6dfbefdSBarry Smith   SNESGetNPC - Gets a nonlinear preconditioning solver SNES` to be used to precondition the original nonlinear solver.
571331823bd8SMatthew G Knepley 
5714*0b4b7b1cSBarry Smith   Not Collective; but any changes to the obtained the `pc` object must be applied collectively
571531823bd8SMatthew G Knepley 
571631823bd8SMatthew G Knepley   Input Parameter:
5717f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
571831823bd8SMatthew G Knepley 
571931823bd8SMatthew G Knepley   Output Parameter:
5720e4094ef1SJacob Faibussowitsch . pc - preconditioner context
572131823bd8SMatthew G Knepley 
5722f6dfbefdSBarry Smith   Options Database Key:
5723f6dfbefdSBarry Smith . -npc_snes_type <type> - set the type of the `SNES` to use as the nonlinear preconditioner
5724b5badacbSBarry Smith 
5725*0b4b7b1cSBarry Smith   Level: advanced
5726dc4c0fb0SBarry Smith 
572795452b02SPatrick Sanan   Notes:
5728*0b4b7b1cSBarry Smith   If a `SNES` was previously set with `SNESSetNPC()` then that value is returned, otherwise a new `SNES` object is created that will
5729*0b4b7b1cSBarry Smith   be used as the nonlinear preconditioner for the current `SNES`.
5730be95d8f1SBarry Smith 
5731f6dfbefdSBarry Smith   The (preconditioner) `SNES` returned automatically inherits the same nonlinear function and Jacobian supplied to the original
5732f6dfbefdSBarry Smith   `SNES`
5733951fe5abSBarry Smith 
57341cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESHasNPC()`, `SNES`, `SNESCreate()`
573531823bd8SMatthew G Knepley @*/
5736d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPC(SNES snes, SNES *pc)
5737d71ae5a4SJacob Faibussowitsch {
5738a64e098fSPeter Brune   const char *optionsprefix;
573931823bd8SMatthew G Knepley 
574031823bd8SMatthew G Knepley   PetscFunctionBegin;
574131823bd8SMatthew G Knepley   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
57424f572ea9SToby Isaac   PetscAssertPointer(pc, 2);
5743efd4aadfSBarry Smith   if (!snes->npc) {
5744ec785e5bSStefano Zampini     void *ctx;
5745ec785e5bSStefano Zampini 
57469566063dSJacob Faibussowitsch     PetscCall(SNESCreate(PetscObjectComm((PetscObject)snes), &snes->npc));
57479566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->npc, (PetscObject)snes, 1));
57489566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
57499566063dSJacob Faibussowitsch     PetscCall(SNESSetOptionsPrefix(snes->npc, optionsprefix));
57509566063dSJacob Faibussowitsch     PetscCall(SNESAppendOptionsPrefix(snes->npc, "npc_"));
5751fb87a551SStefano Zampini     if (snes->ops->usercompute) {
5752fb87a551SStefano Zampini       PetscCall(SNESSetComputeApplicationContext(snes, snes->ops->usercompute, snes->ops->userdestroy));
5753fb87a551SStefano Zampini     } else {
5754ec785e5bSStefano Zampini       PetscCall(SNESGetApplicationContext(snes, &ctx));
5755ec785e5bSStefano Zampini       PetscCall(SNESSetApplicationContext(snes->npc, ctx));
5756fb87a551SStefano Zampini     }
57579566063dSJacob Faibussowitsch     PetscCall(SNESSetCountersReset(snes->npc, PETSC_FALSE));
575831823bd8SMatthew G Knepley   }
5759efd4aadfSBarry Smith   *pc = snes->npc;
57603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
576131823bd8SMatthew G Knepley }
576231823bd8SMatthew G Knepley 
57633ad1a0b9SPatrick Farrell /*@
5764*0b4b7b1cSBarry Smith   SNESHasNPC - Returns whether a nonlinear preconditioner is associated with the given `SNES`
57653ad1a0b9SPatrick Farrell 
57663ad1a0b9SPatrick Farrell   Not Collective
57673ad1a0b9SPatrick Farrell 
57683ad1a0b9SPatrick Farrell   Input Parameter:
5769f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
57703ad1a0b9SPatrick Farrell 
57713ad1a0b9SPatrick Farrell   Output Parameter:
5772420bcc1bSBarry Smith . has_npc - whether the `SNES` has a nonlinear preconditioner or not
57733ad1a0b9SPatrick Farrell 
57743ad1a0b9SPatrick Farrell   Level: developer
57753ad1a0b9SPatrick Farrell 
57761cc06b55SBarry Smith .seealso: [](ch_snes), `SNESSetNPC()`, `SNESGetNPC()`
57773ad1a0b9SPatrick Farrell @*/
5778d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc)
5779d71ae5a4SJacob Faibussowitsch {
57803ad1a0b9SPatrick Farrell   PetscFunctionBegin;
57813ad1a0b9SPatrick Farrell   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5782efd4aadfSBarry Smith   *has_npc = (PetscBool)(snes->npc ? PETSC_TRUE : PETSC_FALSE);
57833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57843ad1a0b9SPatrick Farrell }
57853ad1a0b9SPatrick Farrell 
5786c40d0f55SPeter Brune /*@
5787*0b4b7b1cSBarry Smith   SNESSetNPCSide - Sets the nonlinear preconditioning side used by the given `SNES`.
5788c40d0f55SPeter Brune 
5789c3339decSBarry Smith   Logically Collective
5790c40d0f55SPeter Brune 
5791c40d0f55SPeter Brune   Input Parameter:
5792f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5793c40d0f55SPeter Brune 
5794c40d0f55SPeter Brune   Output Parameter:
5795c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5796c40d0f55SPeter Brune .vb
57972d547940SBarry Smith       PC_LEFT  - left preconditioning
57982d547940SBarry Smith       PC_RIGHT - right preconditioning (default for most nonlinear solvers)
5799c40d0f55SPeter Brune .ve
5800c40d0f55SPeter Brune 
5801f6dfbefdSBarry Smith   Options Database Key:
580267b8a455SSatish Balay . -snes_npc_side <right,left> - nonlinear preconditioner side
5803c40d0f55SPeter Brune 
5804dc4c0fb0SBarry Smith   Level: intermediate
5805dc4c0fb0SBarry Smith 
5806f6dfbefdSBarry Smith   Note:
5807f6dfbefdSBarry Smith   `SNESNRICHARDSON` and `SNESNCG` only support left preconditioning.
58082d547940SBarry Smith 
5809420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESNRICHARDSON`, `SNESNCG`, `SNESType`, `SNESGetNPCSide()`, `KSPSetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5810c40d0f55SPeter Brune @*/
5811d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetNPCSide(SNES snes, PCSide side)
5812d71ae5a4SJacob Faibussowitsch {
5813c40d0f55SPeter Brune   PetscFunctionBegin;
5814c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5815c40d0f55SPeter Brune   PetscValidLogicalCollectiveEnum(snes, side, 2);
5816b552625fSStefano Zampini   if (side == PC_SIDE_DEFAULT) side = PC_RIGHT;
581754c59aa7SJacob Faibussowitsch   PetscCheck((side == PC_LEFT) || (side == PC_RIGHT), PetscObjectComm((PetscObject)snes), PETSC_ERR_ARG_WRONG, "Only PC_LEFT and PC_RIGHT are supported");
5818efd4aadfSBarry Smith   snes->npcside = side;
58193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5820c40d0f55SPeter Brune }
5821c40d0f55SPeter Brune 
5822c40d0f55SPeter Brune /*@
5823be95d8f1SBarry Smith   SNESGetNPCSide - Gets the preconditioning side.
5824c40d0f55SPeter Brune 
5825c40d0f55SPeter Brune   Not Collective
5826c40d0f55SPeter Brune 
5827c40d0f55SPeter Brune   Input Parameter:
5828f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
5829c40d0f55SPeter Brune 
5830c40d0f55SPeter Brune   Output Parameter:
5831c40d0f55SPeter Brune . side - the preconditioning side, where side is one of
5832c40d0f55SPeter Brune .vb
5833f6dfbefdSBarry Smith       `PC_LEFT` - left preconditioning
5834f6dfbefdSBarry Smith       `PC_RIGHT` - right preconditioning (default for most nonlinear solvers)
5835c40d0f55SPeter Brune .ve
5836c40d0f55SPeter Brune 
5837c40d0f55SPeter Brune   Level: intermediate
5838c40d0f55SPeter Brune 
5839420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESSetNPCSide()`, `KSPGetPCSide()`, `PC_LEFT`, `PC_RIGHT`, `PCSide`
5840c40d0f55SPeter Brune @*/
5841d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetNPCSide(SNES snes, PCSide *side)
5842d71ae5a4SJacob Faibussowitsch {
5843c40d0f55SPeter Brune   PetscFunctionBegin;
5844c40d0f55SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
58454f572ea9SToby Isaac   PetscAssertPointer(side, 2);
5846efd4aadfSBarry Smith   *side = snes->npcside;
58473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5848c40d0f55SPeter Brune }
5849c40d0f55SPeter Brune 
58509e764e56SPeter Brune /*@
5851*0b4b7b1cSBarry Smith   SNESSetLineSearch - Sets the `SNESLineSearch` to be used for a given `SNES`
58529e764e56SPeter Brune 
5853c3339decSBarry Smith   Collective
58549e764e56SPeter Brune 
58559e764e56SPeter Brune   Input Parameters:
5856f6dfbefdSBarry Smith + snes       - iterative context obtained from `SNESCreate()`
58579e764e56SPeter Brune - linesearch - the linesearch object
58589e764e56SPeter Brune 
5859dc4c0fb0SBarry Smith   Level: developer
5860dc4c0fb0SBarry Smith 
5861f6dfbefdSBarry Smith   Note:
5862420bcc1bSBarry Smith   This is almost never used, rather one uses `SNESGetLineSearch()` to retrieve the line search and set options on it
58639e764e56SPeter Brune   to configure it using the API).
58649e764e56SPeter Brune 
5865420bcc1bSBarry Smith .seealso: [](ch_snes), `SNES`, `SNESLineSearch`, `SNESGetLineSearch()`
58669e764e56SPeter Brune @*/
5867d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch)
5868d71ae5a4SJacob Faibussowitsch {
58699e764e56SPeter Brune   PetscFunctionBegin;
58709e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
5871f1c6b773SPeter Brune   PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2);
58729e764e56SPeter Brune   PetscCheckSameComm(snes, 1, linesearch, 2);
58739566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)linesearch));
58749566063dSJacob Faibussowitsch   PetscCall(SNESLineSearchDestroy(&snes->linesearch));
5875f5af7f23SKarl Rupp 
58769e764e56SPeter Brune   snes->linesearch = linesearch;
58773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58789e764e56SPeter Brune }
58799e764e56SPeter Brune 
5880a34ceb2aSJed Brown /*@
5881420bcc1bSBarry Smith   SNESGetLineSearch - Returns the line search context possibly set with `SNESSetLineSearch()`
5882f6dfbefdSBarry Smith   or creates a default line search instance associated with the `SNES` and returns it.
58839e764e56SPeter Brune 
58849e764e56SPeter Brune   Not Collective
58859e764e56SPeter Brune 
58869e764e56SPeter Brune   Input Parameter:
5887f6dfbefdSBarry Smith . snes - iterative context obtained from `SNESCreate()`
58889e764e56SPeter Brune 
58899e764e56SPeter Brune   Output Parameter:
58909e764e56SPeter Brune . linesearch - linesearch context
58919e764e56SPeter Brune 
5892162e0bf5SPeter Brune   Level: beginner
58939e764e56SPeter Brune 
58941cc06b55SBarry Smith .seealso: [](ch_snes), `SNESLineSearch`, `SNESSetLineSearch()`, `SNESLineSearchCreate()`
58959e764e56SPeter Brune @*/
5896d71ae5a4SJacob Faibussowitsch PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch)
5897d71ae5a4SJacob Faibussowitsch {
58989e764e56SPeter Brune   const char *optionsprefix;
58999e764e56SPeter Brune 
59009e764e56SPeter Brune   PetscFunctionBegin;
59019e764e56SPeter Brune   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
59024f572ea9SToby Isaac   PetscAssertPointer(linesearch, 2);
59039e764e56SPeter Brune   if (!snes->linesearch) {
59049566063dSJacob Faibussowitsch     PetscCall(SNESGetOptionsPrefix(snes, &optionsprefix));
59059566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch));
59069566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchSetSNES(snes->linesearch, snes));
59079566063dSJacob Faibussowitsch     PetscCall(SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix));
59089566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)snes->linesearch, (PetscObject)snes, 1));
59099e764e56SPeter Brune   }
59109e764e56SPeter Brune   *linesearch = snes->linesearch;
59113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59129e764e56SPeter Brune }
5913